diff --git a/controllers/toolchainclustercache/namespace_predicate.go b/controllers/toolchainclustercache/namespace_predicate.go new file mode 100644 index 00000000..4b80c21c --- /dev/null +++ b/controllers/toolchainclustercache/namespace_predicate.go @@ -0,0 +1,30 @@ +package toolchainclustercache + +import ( + "sigs.k8s.io/controller-runtime/pkg/event" +) + +// CreateAndUpdateOnlyPredicate will filter out all events out of the provided namespace +type namespacePredicate struct { + namespace string +} + +// Update allows events only in the given namespace +func (p namespacePredicate) Update(e event.UpdateEvent) bool { + return e.ObjectNew.GetNamespace() == p.namespace +} + +// Create allows events only in the given namespace +func (p namespacePredicate) Create(e event.CreateEvent) bool { + return e.Object.GetNamespace() == p.namespace +} + +// Delete allows events only in the given namespace +func (p namespacePredicate) Delete(e event.DeleteEvent) bool { + return e.Object.GetNamespace() == p.namespace +} + +// Generic allows events only in the given namespace +func (p namespacePredicate) Generic(e event.GenericEvent) bool { + return e.Object.GetNamespace() == p.namespace +} diff --git a/controllers/toolchainclustercache/namespace_predicate_test.go b/controllers/toolchainclustercache/namespace_predicate_test.go new file mode 100644 index 00000000..192623ce --- /dev/null +++ b/controllers/toolchainclustercache/namespace_predicate_test.go @@ -0,0 +1,101 @@ +package toolchainclustercache + +import ( + "testing" + + toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" + "github.com/stretchr/testify/assert" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/event" +) + +func TestNamespacePredicate(t *testing.T) { + // given + predicate := namespacePredicate{ + namespace: "matching-namespace", + } + + tests := map[string]struct { + namespace string + expected bool + }{ + "with matching namespace": { + namespace: "matching-namespace", + expected: true, + }, + + "without matching namespace": { + namespace: "non-matching-namespace", + expected: false, + }, + + "without any namespace": { + namespace: "", + expected: false, + }, + } + + for testName, data := range tests { + t.Run(testName, func(t *testing.T) { + tc := &toolchainv1alpha1.ToolchainCluster{ + ObjectMeta: v1.ObjectMeta{ + Name: "tc-name", + Namespace: data.namespace, + }, + } + t.Run("update event", func(t *testing.T) { + // given + ev := event.UpdateEvent{ + ObjectNew: tc, + // we don't care about the old version of the object + ObjectOld: nil, + } + + // when + shouldReconcile := predicate.Update(ev) + + // then + assert.Equal(t, data.expected, shouldReconcile) + }) + + t.Run("create event", func(t *testing.T) { + // given + ev := event.CreateEvent{ + Object: tc, + } + + // when + shouldReconcile := predicate.Create(ev) + + // then + assert.Equal(t, data.expected, shouldReconcile) + }) + + t.Run("generic event", func(t *testing.T) { + // given + ev := event.GenericEvent{ + Object: tc, + } + + // when + shouldReconcile := predicate.Generic(ev) + + // then + assert.Equal(t, data.expected, shouldReconcile) + }) + + t.Run("delete event", func(t *testing.T) { + // given + ev := event.DeleteEvent{ + Object: tc, + } + + // when + shouldReconcile := predicate.Delete(ev) + + // then + assert.Equal(t, data.expected, shouldReconcile) + }) + }) + } +} diff --git a/controllers/toolchainclustercache/toolchaincluster_cache_controller.go b/controllers/toolchainclustercache/toolchaincluster_cache_controller.go index 9adb8fbb..b39f64fd 100644 --- a/controllers/toolchainclustercache/toolchaincluster_cache_controller.go +++ b/controllers/toolchainclustercache/toolchaincluster_cache_controller.go @@ -9,6 +9,7 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -23,13 +24,14 @@ func NewReconciler(mgr manager.Manager, namespace string, timeout time.Duration) client: mgr.GetClient(), scheme: mgr.GetScheme(), clusterCacheService: clusterCacheService, + namespace: namespace, } } // SetupWithManager sets up the controller with the Manager. func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&toolchainv1alpha1.ToolchainCluster{}). + For(&toolchainv1alpha1.ToolchainCluster{}, builder.WithPredicates(namespacePredicate{namespace: r.namespace})). Complete(r) } @@ -38,6 +40,7 @@ type Reconciler struct { client client.Client scheme *runtime.Scheme clusterCacheService cluster.ToolchainClusterService + namespace string } // Reconcile reads that state of the cluster for a ToolchainCluster object and makes changes based on the state read