internal/predicate/predicate.go (88 lines of code) (raw):
package predicate
import (
v1 "k8s.io/api/apps/v1"
v12 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
"reflect"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
func TeamcityEventPredicates() predicate.Predicate {
return predicate.Funcs{
CreateFunc: func(createEvent event.CreateEvent) bool {
return true
},
UpdateFunc: func(updateEvent event.UpdateEvent) bool {
return true
},
DeleteFunc: func(deleteEvent event.DeleteEvent) bool {
return !deleteEvent.DeleteStateUnknown
},
GenericFunc: func(genericEvent event.GenericEvent) bool {
return true
},
}
}
func StatefulSetEventPredicates() predicate.Predicate {
return predicate.Funcs{
CreateFunc: func(createEvent event.CreateEvent) bool {
return true
},
UpdateFunc: func(updateEvent event.UpdateEvent) bool {
return shouldFilterOutUpdateEventForStatefulSet(updateEvent)
},
DeleteFunc: func(deleteEvent event.DeleteEvent) bool {
return !deleteEvent.DeleteStateUnknown
},
GenericFunc: func(genericEvent event.GenericEvent) bool {
return true
},
}
}
func PersistentVolumeClaimEventPredicates() predicate.Predicate {
return predicate.Funcs{
CreateFunc: func(createEvent event.CreateEvent) bool {
return true
},
UpdateFunc: func(updateEvent event.UpdateEvent) bool {
return shouldFilterOutUpdateEventForPersistentVolumeClaim(updateEvent)
},
DeleteFunc: func(deleteEvent event.DeleteEvent) bool {
return !deleteEvent.DeleteStateUnknown
},
GenericFunc: func(genericEvent event.GenericEvent) bool {
return true
},
}
}
func shouldFilterOutUpdateEventForPersistentVolumeClaim(event event.UpdateEvent) bool {
oldPVC, ok := event.ObjectOld.(*v12.PersistentVolumeClaim)
if !ok {
return false
}
newPVC, ok := event.ObjectNew.(*v12.PersistentVolumeClaim)
if !ok {
return false
}
if equal(oldPVC.Spec, newPVC.Spec) {
return false
}
return true
}
func shouldFilterOutUpdateEventForStatefulSet(event event.UpdateEvent) bool {
//attempt to cast updated object to StatefulSet
//if casting fails - controller should skip this event
oldStatefulSet, ok := event.ObjectOld.(*v1.StatefulSet)
if !ok {
return false
}
newStatefulSet, ok := event.ObjectNew.(*v1.StatefulSet)
if !ok {
return false
}
//if spec of StatefulSet did not change, the event is ignored
if equal(oldStatefulSet.Spec, newStatefulSet.Spec) {
return false
}
return true
}
func equal(x, y interface{}) bool {
//DeepEqual is not always capable of detecting identical objects due to various defaults and type conversions
//DeepDerivative is more reliable way since it does not care for defaults and types as much
return reflect.DeepEqual(x, y) || equality.Semantic.DeepDerivative(x, y)
}