2020-01-07 15:13:57 -08:00
package operator
import (
2021-10-29 09:54:51 +01:00
"fmt"
2021-02-06 09:19:23 +05:30
"strings"
2021-10-29 09:54:51 +01:00
"time"
2021-02-06 09:19:23 +05:30
2020-03-17 11:05:20 -07:00
"github.com/go-logr/logr"
2022-05-17 13:12:43 +02:00
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
2020-10-07 11:12:31 -07:00
"github.com/kyverno/kyverno/pkg/engine/context"
2020-01-07 15:13:57 -08:00
)
2022-05-17 08:19:03 +02:00
// OperatorHandler provides interface to manage types
2020-01-07 15:13:57 -08:00
type OperatorHandler interface {
2021-07-28 19:54:50 +03:00
Evaluate ( key , value interface { } ) bool
2020-11-28 23:29:15 -08:00
validateValueWithStringPattern ( key string , value interface { } ) bool
validateValueWithBoolPattern ( key bool , value interface { } ) bool
validateValueWithIntPattern ( key int64 , value interface { } ) bool
validateValueWithFloatPattern ( key float64 , value interface { } ) bool
2020-01-07 15:13:57 -08:00
validateValueWithMapPattern ( key map [ string ] interface { } , value interface { } ) bool
validateValueWithSlicePattern ( key [ ] interface { } , value interface { } ) bool
}
2022-05-17 08:19:03 +02:00
// VariableSubstitutionHandler defines the handler function for variable substitution
2020-03-17 11:05:20 -07:00
type VariableSubstitutionHandler = func ( log logr . Logger , ctx context . EvalInterface , pattern interface { } ) ( interface { } , error )
2020-01-07 15:13:57 -08:00
2022-05-17 08:19:03 +02:00
// CreateOperatorHandler returns the operator handler based on the operator used in condition
2022-05-17 13:12:43 +02:00
func CreateOperatorHandler ( log logr . Logger , ctx context . EvalInterface , op kyvernov1 . ConditionOperator ) OperatorHandler {
2020-10-29 15:00:22 -07:00
str := strings . ToLower ( string ( op ) )
switch str {
2022-05-17 13:12:43 +02:00
case strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "Equal" ] ) ) ,
strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "Equals" ] ) ) :
2021-07-28 19:54:50 +03:00
return NewEqualHandler ( log , ctx )
2020-10-29 15:00:22 -07:00
2022-05-17 13:12:43 +02:00
case strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "NotEqual" ] ) ) ,
strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "NotEquals" ] ) ) :
2021-07-28 19:54:50 +03:00
return NewNotEqualHandler ( log , ctx )
2020-10-29 15:00:22 -07:00
2021-10-27 05:59:42 +05:30
// deprecated
2022-05-17 13:12:43 +02:00
case strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "In" ] ) ) :
2021-07-28 19:54:50 +03:00
return NewInHandler ( log , ctx )
2020-10-29 15:00:22 -07:00
2022-05-17 13:12:43 +02:00
case strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "AnyIn" ] ) ) :
2021-10-27 05:59:42 +05:30
return NewAnyInHandler ( log , ctx )
2022-05-17 13:12:43 +02:00
case strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "AllIn" ] ) ) :
2021-10-27 05:59:42 +05:30
return NewAllInHandler ( log , ctx )
// deprecated
2022-05-17 13:12:43 +02:00
case strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "NotIn" ] ) ) :
2021-07-28 19:54:50 +03:00
return NewNotInHandler ( log , ctx )
2020-10-29 15:00:22 -07:00
2022-05-17 13:12:43 +02:00
case strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "AnyNotIn" ] ) ) :
2021-10-27 05:59:42 +05:30
return NewAnyNotInHandler ( log , ctx )
2022-05-17 13:12:43 +02:00
case strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "AllNotIn" ] ) ) :
2021-10-27 05:59:42 +05:30
return NewAllNotInHandler ( log , ctx )
2022-05-17 13:12:43 +02:00
case strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "GreaterThanOrEquals" ] ) ) ,
strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "GreaterThan" ] ) ) ,
strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "LessThanOrEquals" ] ) ) ,
strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "LessThan" ] ) ) :
2021-07-28 19:54:50 +03:00
return NewNumericOperatorHandler ( log , ctx , op )
2021-02-06 09:19:23 +05:30
2022-05-17 13:12:43 +02:00
case strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "DurationGreaterThanOrEquals" ] ) ) ,
strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "DurationGreaterThan" ] ) ) ,
strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "DurationLessThanOrEquals" ] ) ) ,
strings . ToLower ( string ( kyvernov1 . ConditionOperators [ "DurationLessThan" ] ) ) :
2022-08-18 18:54:59 +05:30
log . V ( 2 ) . Info ( "DEPRECATED: The Duration* operators have been replaced with the other existing operators that now also support duration values" , "operator" , str )
2021-07-30 16:11:52 -04:00
return NewDurationOperatorHandler ( log , ctx , op )
2020-01-07 15:13:57 -08:00
default :
2022-08-18 18:54:59 +05:30
log . V ( 2 ) . Info ( "operator not supported" , "operator" , str )
2020-01-07 15:13:57 -08:00
}
2020-10-29 15:00:22 -07:00
2020-01-07 15:13:57 -08:00
return nil
}
2021-10-29 09:54:51 +01:00
func parseDuration ( key , value interface { } ) ( * time . Duration , * time . Duration , error ) {
var keyDuration * time . Duration
var valueDuration * time . Duration
var err error
// We need to first ensure at least one of the values is actually a duration string.
switch typedKey := key . ( type ) {
case string :
duration , err := time . ParseDuration ( typedKey )
if err == nil && key != "0" {
keyDuration = & duration
}
}
switch typedValue := value . ( type ) {
case string :
duration , err := time . ParseDuration ( typedValue )
if err == nil && value != "0" {
valueDuration = & duration
}
}
if keyDuration == nil && valueDuration == nil {
return keyDuration , valueDuration , fmt . Errorf ( "neither value is a duration" )
}
if keyDuration == nil {
var duration time . Duration
switch typedKey := key . ( type ) {
case int :
duration = time . Duration ( typedKey ) * time . Second
case int64 :
duration = time . Duration ( typedKey ) * time . Second
case float64 :
duration = time . Duration ( typedKey ) * time . Second
default :
return keyDuration , valueDuration , fmt . Errorf ( "no valid duration value" )
}
keyDuration = & duration
}
if valueDuration == nil {
var duration time . Duration
switch typedValue := value . ( type ) {
case int :
duration = time . Duration ( typedValue ) * time . Second
case int64 :
duration = time . Duration ( typedValue ) * time . Second
case float64 :
duration = time . Duration ( typedValue ) * time . Second
default :
return keyDuration , valueDuration , fmt . Errorf ( "no valid duration value" )
}
valueDuration = & duration
}
return keyDuration , valueDuration , err
}