2021-07-30 16:11:52 -04:00
package operator
import (
"fmt"
"time"
"github.com/go-logr/logr"
2022-05-17 13:12:43 +02:00
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
2021-07-30 16:11:52 -04:00
"github.com/kyverno/kyverno/pkg/engine/context"
)
2022-05-17 08:19:03 +02:00
// NewDurationOperatorHandler returns handler to manage the provided duration operations (>, >=, <=, <)
2022-05-17 13:12:43 +02:00
func NewDurationOperatorHandler ( log logr . Logger , ctx context . EvalInterface , op kyvernov1 . ConditionOperator ) OperatorHandler {
2021-07-30 16:11:52 -04:00
return DurationOperatorHandler {
ctx : ctx ,
log : log ,
condition : op ,
}
}
2022-05-17 08:19:03 +02:00
// DurationOperatorHandler provides implementation to handle Duration Operations associated with policies
2021-07-30 16:11:52 -04:00
type DurationOperatorHandler struct {
ctx context . EvalInterface
log logr . Logger
2022-05-17 13:12:43 +02:00
condition kyvernov1 . ConditionOperator
2021-07-30 16:11:52 -04:00
}
// durationCompareByCondition compares a time.Duration key with a time.Duration value on the basis of the provided operator
2022-05-17 13:12:43 +02:00
func durationCompareByCondition ( key time . Duration , value time . Duration , op kyvernov1 . ConditionOperator , log logr . Logger ) bool {
2021-07-30 16:11:52 -04:00
switch op {
2022-05-17 13:12:43 +02:00
case kyvernov1 . ConditionOperators [ "DurationGreaterThanOrEquals" ] :
2021-07-30 16:11:52 -04:00
return key >= value
2022-05-17 13:12:43 +02:00
case kyvernov1 . ConditionOperators [ "DurationGreaterThan" ] :
2021-07-30 16:11:52 -04:00
return key > value
2022-05-17 13:12:43 +02:00
case kyvernov1 . ConditionOperators [ "DurationLessThanOrEquals" ] :
2021-07-30 16:11:52 -04:00
return key <= value
2022-05-17 13:12:43 +02:00
case kyvernov1 . ConditionOperators [ "DurationLessThan" ] :
2021-07-30 16:11:52 -04:00
return key < value
default :
2022-08-18 18:54:59 +05:30
log . V ( 2 ) . Info ( fmt . Sprintf ( "Expected operator, one of [DurationGreaterThanOrEquals, DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan], found %s" , op ) )
2021-07-30 16:11:52 -04:00
return false
}
}
func ( doh DurationOperatorHandler ) Evaluate ( key , value interface { } ) bool {
switch typedKey := key . ( type ) {
case int :
return doh . validateValueWithIntPattern ( int64 ( typedKey ) , value )
case int64 :
return doh . validateValueWithIntPattern ( typedKey , value )
case float64 :
return doh . validateValueWithFloatPattern ( typedKey , value )
case string :
return doh . validateValueWithStringPattern ( typedKey , value )
default :
2022-08-18 18:54:59 +05:30
doh . log . V ( 2 ) . Info ( "Unsupported type" , "value" , typedKey , "type" , fmt . Sprintf ( "%T" , typedKey ) )
2021-07-30 16:11:52 -04:00
return false
}
}
func ( doh DurationOperatorHandler ) validateValueWithIntPattern ( key int64 , value interface { } ) bool {
switch typedValue := value . ( type ) {
case int :
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( time . Duration ( key ) * time . Second , time . Duration ( typedValue ) * time . Second , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
case int64 :
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( time . Duration ( key ) * time . Second , time . Duration ( typedValue ) * time . Second , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
case float64 :
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( time . Duration ( key ) * time . Second , time . Duration ( typedValue ) * time . Second , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
case string :
duration , err := time . ParseDuration ( typedValue )
if err == nil {
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( time . Duration ( key ) * time . Second , duration , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
}
2021-10-12 23:29:20 +02:00
doh . log . Error ( fmt . Errorf ( "parse error: " ) , "Failed to parse time duration from the string value" )
2021-07-30 16:11:52 -04:00
return false
default :
2022-08-18 18:54:59 +05:30
doh . log . V ( 2 ) . Info ( "Unexpected type" , "value" , value , "type" , fmt . Sprintf ( "%T" , value ) )
2021-07-30 16:11:52 -04:00
return false
}
}
func ( doh DurationOperatorHandler ) validateValueWithFloatPattern ( key float64 , value interface { } ) bool {
switch typedValue := value . ( type ) {
case int :
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( time . Duration ( key ) * time . Second , time . Duration ( typedValue ) * time . Second , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
case int64 :
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( time . Duration ( key ) * time . Second , time . Duration ( typedValue ) * time . Second , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
case float64 :
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( time . Duration ( key ) * time . Second , time . Duration ( typedValue ) * time . Second , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
case string :
duration , err := time . ParseDuration ( typedValue )
if err == nil {
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( time . Duration ( key ) * time . Second , duration , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
}
2021-10-12 23:29:20 +02:00
doh . log . Error ( fmt . Errorf ( "parse error: " ) , "Failed to parse time duration from the string value" )
2021-07-30 16:11:52 -04:00
return false
default :
2022-08-18 18:54:59 +05:30
doh . log . V ( 2 ) . Info ( "Unexpected type" , "value" , value , "type" , fmt . Sprintf ( "%T" , value ) )
2021-07-30 16:11:52 -04:00
return false
}
}
func ( doh DurationOperatorHandler ) validateValueWithStringPattern ( key string , value interface { } ) bool {
duration , err := time . ParseDuration ( key )
if err != nil {
doh . log . Error ( err , "Failed to parse time duration from the string key" )
return false
}
switch typedValue := value . ( type ) {
case int :
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( duration , time . Duration ( typedValue ) * time . Second , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
case int64 :
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( duration , time . Duration ( typedValue ) * time . Second , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
case float64 :
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( duration , time . Duration ( typedValue ) * time . Second , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
case string :
durationValue , err := time . ParseDuration ( typedValue )
if err == nil {
2022-04-25 13:51:49 +02:00
return durationCompareByCondition ( duration , durationValue , doh . condition , doh . log )
2021-07-30 16:11:52 -04:00
}
2021-10-12 23:29:20 +02:00
doh . log . Error ( fmt . Errorf ( "parse error: " ) , "Failed to parse time duration from the string value" )
2021-07-30 16:11:52 -04:00
return false
default :
2022-08-18 18:54:59 +05:30
doh . log . V ( 2 ) . Info ( "Unexpected type" , "value" , value , "type" , fmt . Sprintf ( "%T" , value ) )
2021-07-30 16:11:52 -04:00
return false
}
}
// the following functions are unreachable because the key is strictly supposed to be a duration
// still the following functions are just created to make DurationOperatorHandler struct implement OperatorHandler interface
func ( doh DurationOperatorHandler ) validateValueWithBoolPattern ( key bool , value interface { } ) bool {
return false
}
2022-05-17 08:19:03 +02:00
2021-07-30 16:11:52 -04:00
func ( doh DurationOperatorHandler ) validateValueWithMapPattern ( key map [ string ] interface { } , value interface { } ) bool {
return false
}
2022-05-17 08:19:03 +02:00
2021-07-30 16:11:52 -04:00
func ( doh DurationOperatorHandler ) validateValueWithSlicePattern ( key [ ] interface { } , value interface { } ) bool {
return false
}