Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: extract common predicates to k8s utils #1714

Merged
merged 5 commits into from
Nov 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion instrumentor/controllers/instrumentationdevice/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
odigosv1 "github.com/odigos-io/odigos/api/odigos/v1alpha1"
"github.com/odigos-io/odigos/common"
"github.com/odigos-io/odigos/instrumentor/controllers/utils"
odigospredicate "github.com/odigos-io/odigos/k8sutils/pkg/predicate"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -110,7 +111,7 @@ func SetupWithManager(mgr ctrl.Manager) error {
ControllerManagedBy(mgr).
Named("instrumentationdevice-configmaps").
For(&corev1.ConfigMap{}).
WithEventFilter(&utils.OnlyUpdatesPredicate{}).
WithEventFilter(&odigospredicate.OnlyUpdatesPredicate{}).
Complete(&OdigosConfigReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Expand Down
4 changes: 2 additions & 2 deletions instrumentor/controllers/startlangdetection/manager.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package startlangdetection

import (
"github.com/odigos-io/odigos/instrumentor/controllers/utils"
odigospredicate "github.com/odigos-io/odigos/k8sutils/pkg/predicate"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -64,7 +64,7 @@ func SetupWithManager(mgr ctrl.Manager) error {
ControllerManagedBy(mgr).
Named("startlangdetection-configmaps").
For(&corev1.ConfigMap{}).
WithEventFilter(&utils.OnlyUpdatesPredicate{}).
WithEventFilter(&odigospredicate.OnlyUpdatesPredicate{}).
Complete(&OdigosConfigReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Expand Down
18 changes: 0 additions & 18 deletions instrumentor/controllers/utils/predicate.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/event"
)

type OnlyUpdatesPredicate struct{}

func (o OnlyUpdatesPredicate) Create(e event.CreateEvent) bool {
return false
}

func (i OnlyUpdatesPredicate) Update(e event.UpdateEvent) bool {
return true
}

func (i OnlyUpdatesPredicate) Delete(e event.DeleteEvent) bool {
return false
}

func (i OnlyUpdatesPredicate) Generic(e event.GenericEvent) bool {
return false
}

type OtelSdkInstrumentationRulePredicate struct{}

func (o OtelSdkInstrumentationRulePredicate) Create(e event.CreateEvent) bool {
Expand Down
55 changes: 55 additions & 0 deletions k8sutils/pkg/predicate/cgbecomesready.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package predicate

import (
odigosv1 "github.com/odigos-io/odigos/api/odigos/v1alpha1"
"sigs.k8s.io/controller-runtime/pkg/event"
cr_predicate "sigs.k8s.io/controller-runtime/pkg/predicate"
)

// this event filter will only trigger reconciliation when the collectors group was not ready and now it is ready.
// some controllers in odigos reacts to this specific event, and should not be triggered by other events such as spec updates or status conditions changes.
type CgBecomesReadyPredicate struct{}

func (i *CgBecomesReadyPredicate) Create(e event.CreateEvent) bool {
if e.Object == nil {
return false
}

cg, ok := e.Object.(*odigosv1.CollectorsGroup)
if !ok {
return false
}
return cg.Status.Ready
}

func (i *CgBecomesReadyPredicate) Update(e event.UpdateEvent) bool {

if e.ObjectOld == nil || e.ObjectNew == nil {
return false
}

oldCollectorGroup, ok := e.ObjectOld.(*odigosv1.CollectorsGroup)
if !ok {
return false
}
newCollectorGroup, ok := e.ObjectNew.(*odigosv1.CollectorsGroup)
if !ok {
return false
}

wasReady := oldCollectorGroup.Status.Ready
nowReady := newCollectorGroup.Status.Ready
becameReady := !wasReady && nowReady

return becameReady
}

func (i *CgBecomesReadyPredicate) Delete(e event.DeleteEvent) bool {
return false
}

func (i *CgBecomesReadyPredicate) Generic(e event.GenericEvent) bool {
return false
}

var _ cr_predicate.Predicate = &CgBecomesReadyPredicate{}
33 changes: 33 additions & 0 deletions k8sutils/pkg/predicate/existence.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package predicate

import (
"sigs.k8s.io/controller-runtime/pkg/event"
cr_predicate "sigs.k8s.io/controller-runtime/pkg/predicate"
)

// existence predicate only allows create and delete events.
// it is useful when the controller only reacts to the presence of an object (e.g. if it exists or not),
// and not to it's content or status changes.
//
// Notice these 2 things when using this predicate:
// 1. The event filter will allow events for each object on startup, as all the objects are "created" in the cache.
// 2. If you have important task to do on delete events, make sure it is applied if the event is missed and the controller restarts, since the delete event will not be triggered on controller restart as the object is no longer in k8s.
type ExistencePredicate struct{}

func (o ExistencePredicate) Create(e event.CreateEvent) bool {
return true
}

func (i ExistencePredicate) Update(e event.UpdateEvent) bool {
return false
}

func (i ExistencePredicate) Delete(e event.DeleteEvent) bool {
return true
}

func (i ExistencePredicate) Generic(e event.GenericEvent) bool {
return false
}

var _ cr_predicate.Predicate = &ExistencePredicate{}
84 changes: 84 additions & 0 deletions k8sutils/pkg/predicate/objectname.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package predicate

import (
"github.com/odigos-io/odigos/common/consts"
odigosk8sconsts "github.com/odigos-io/odigos/k8sutils/pkg/consts"
"sigs.k8s.io/controller-runtime/pkg/event"
cr_predicate "sigs.k8s.io/controller-runtime/pkg/predicate"
)

type ObjectNamePredicate struct {
AllowedObjectName string
}

func (o ObjectNamePredicate) Create(e event.CreateEvent) bool {
if e.Object == nil {
return false
}
return e.Object.GetName() == o.AllowedObjectName
blumamir marked this conversation as resolved.
Show resolved Hide resolved
}

func (i ObjectNamePredicate) Update(e event.UpdateEvent) bool {
if e.ObjectNew == nil || e.ObjectOld == nil {
return false
}
return e.ObjectNew.GetName() == i.AllowedObjectName
}

func (i ObjectNamePredicate) Delete(e event.DeleteEvent) bool {
if e.Object == nil {
return false
}
return e.Object.GetName() == i.AllowedObjectName
}

func (i ObjectNamePredicate) Generic(e event.GenericEvent) bool {
if e.Object == nil {
return false
}
return e.Object.GetName() == i.AllowedObjectName
}

var _ cr_predicate.Predicate = &ObjectNamePredicate{}

// This predicate will only allow config map events on the "odigos-config" object,
// and will filter out events for possible other config maps which the reconciler should not handle.
// Example usage:
// import odigospredicates "github.com/odigos-io/odigos/k8sutils/pkg/predicate"
// ...
//
// err = ctrl.NewControllerManagedBy(mgr).
// For(&corev1.ConfigMap{}).
// WithEventFilter(&odigospredicates.OdigosConfigMapPredicate).
// Complete(r)
var OdigosConfigMapPredicate = ObjectNamePredicate{
AllowedObjectName: consts.OdigosConfigurationName,
}

// use this event filter to reconcile only collectors group events for node collectors group objects
// this is useful if you reconcile only depends on changes from the node collectors group and should not react to cluster collectors group changes
// example usage:
// import odigospredicates "github.com/odigos-io/odigos/k8sutils/pkg/predicate"
// ...
//
// err = ctrl.NewControllerManagedBy(mgr).
// For(&odigosv1.CollectorsGroup{}).
// WithEventFilter(&odigospredicates.OdigosCollectorsGroupCluster).
// Complete(r)
var OdigosCollectorsGroupNodePredicate = ObjectNamePredicate{
AllowedObjectName: odigosk8sconsts.OdigosNodeCollectorCollectorGroupName,
}

// use this event filter to reconcile only collectors group events for cluster collectors group objects
// this is useful if you reconcile only depends on changes from the cluster collectors group and should not react to node collectors group changes
// example usage:
// import odigospredicates "github.com/odigos-io/odigos/k8sutils/pkg/predicate"
// ...
//
// err = ctrl.NewControllerManagedBy(mgr).
// For(&odigosv1.CollectorsGroup{}).
// WithEventFilter(&odigospredicates.OdigosCollectorsGroupClusterPredicate).
// Complete(r)
var OdigosCollectorsGroupClusterPredicate = ObjectNamePredicate{
AllowedObjectName: odigosk8sconsts.OdigosClusterCollectorCollectorGroupName,
}
29 changes: 29 additions & 0 deletions k8sutils/pkg/predicate/onlyupdate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package predicate

import (
"sigs.k8s.io/controller-runtime/pkg/event"
cr_predicate "sigs.k8s.io/controller-runtime/pkg/predicate"
)

// This predicate only allows update events.
// It is useful if you handle the initial state when the controller starts, and only need to apply changes
// for example - when monitoring odigos config changes.
type OnlyUpdatesPredicate struct{}

func (o OnlyUpdatesPredicate) Create(e event.CreateEvent) bool {
return false
}

func (i OnlyUpdatesPredicate) Update(e event.UpdateEvent) bool {
return true
}

func (i OnlyUpdatesPredicate) Delete(e event.DeleteEvent) bool {
return false
}

func (i OnlyUpdatesPredicate) Generic(e event.GenericEvent) bool {
return false
}

var _ cr_predicate.Predicate = &OnlyUpdatesPredicate{}
2 changes: 2 additions & 0 deletions scheduler/controllers/destination_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/odigos-io/odigos/k8sutils/pkg/utils"

odigosv1 "github.com/odigos-io/odigos/api/odigos/v1alpha1"
odigospredicates "github.com/odigos-io/odigos/k8sutils/pkg/predicate"
"github.com/odigos-io/odigos/scheduler/controllers/collectorgroups"

"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -67,5 +68,6 @@ func (r *DestinationReconciler) Reconcile(ctx context.Context, req ctrl.Request)
func (r *DestinationReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&odigosv1.Destination{}).
WithEventFilter(&odigospredicates.ExistencePredicate{}). // only care when destinations are created or deleted
Complete(r)
}
Loading
Loading