diff --git a/internal/services/controller/controller.go b/internal/services/controller/controller.go index 271868f0..ff5b6a06 100644 --- a/internal/services/controller/controller.go +++ b/internal/services/controller/controller.go @@ -112,7 +112,7 @@ func New( handledInformers[fmt.Sprintf("%s:autoscaler", eventType)] = custominformers.NewHandledInformer( log, queue, - createEventInformer(f, autoscalerevents.ListOpts), + createEventInformer(f, v, autoscalerevents.ListOpts), eventType, filters.Filters{ { @@ -123,7 +123,7 @@ func New( handledInformers[fmt.Sprintf("%s:oom", eventType)] = custominformers.NewHandledInformer( log, queue, - createEventInformer(f, oomevents.ListOpts), + createEventInformer(f, v, oomevents.ListOpts), eventType, filters.Filters{ { @@ -534,9 +534,11 @@ func getDefaultInformers(f informers.SharedInformerFactory) map[reflect.Type]cac } } -func createEventInformer(f informers.SharedInformerFactory, listOptions func(*metav1.ListOptions)) cache.SharedIndexInformer { +func createEventInformer(f informers.SharedInformerFactory, v version.Interface, listOptions func(*metav1.ListOptions, version.Interface)) cache.SharedIndexInformer { return f.InformerFor(&corev1.Event{}, func(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return v1.NewFilteredEventInformer(client, corev1.NamespaceAll, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, listOptions) + return v1.NewFilteredEventInformer(client, corev1.NamespaceAll, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, func(options *metav1.ListOptions) { + listOptions(options, v) + }) }) } diff --git a/internal/services/controller/controller_test.go b/internal/services/controller/controller_test.go index 9d798669..c5a7d6e6 100644 --- a/internal/services/controller/controller_test.go +++ b/internal/services/controller/controller_test.go @@ -262,7 +262,7 @@ func TestController_HappyPath(t *testing.T) { }, } - version.EXPECT().Full().Return("1.21+").MaxTimes(2) + version.EXPECT().Full().Return("1.21+").MaxTimes(3) clusterID := uuid.New() diff --git a/internal/services/controller/handlers/filters/autoscalerevents/filter.go b/internal/services/controller/handlers/filters/autoscalerevents/filter.go index 4a5b446b..89cc7df7 100644 --- a/internal/services/controller/handlers/filters/autoscalerevents/filter.go +++ b/internal/services/controller/handlers/filters/autoscalerevents/filter.go @@ -3,8 +3,10 @@ package autoscalerevents import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sversion "k8s.io/apimachinery/pkg/util/version" "castai-agent/internal/castai" + "castai-agent/internal/services/version" ) const ( @@ -12,6 +14,8 @@ const ( fieldSelector = "reportingComponent=" + AutoscalerController ) +var minFieldSelectorVersion = k8sversion.MustParseSemantic("1.19.0") + func Filter(_ castai.EventType, obj interface{}) bool { event, ok := obj.(*corev1.Event) if !ok { @@ -20,6 +24,9 @@ func Filter(_ castai.EventType, obj interface{}) bool { return event.ReportingController == AutoscalerController } -func ListOpts(opts *metav1.ListOptions) { - opts.FieldSelector = fieldSelector +func ListOpts(opts *metav1.ListOptions, clusterVersion version.Interface) { + ver, err := k8sversion.ParseSemantic(clusterVersion.Full()) + if err == nil && ver.AtLeast(minFieldSelectorVersion) { + opts.FieldSelector = fieldSelector + } } diff --git a/internal/services/controller/handlers/filters/autoscalerevents/filter_test.go b/internal/services/controller/handlers/filters/autoscalerevents/filter_test.go index 0cb0aab2..b7c26da2 100644 --- a/internal/services/controller/handlers/filters/autoscalerevents/filter_test.go +++ b/internal/services/controller/handlers/filters/autoscalerevents/filter_test.go @@ -3,6 +3,7 @@ package autoscalerevents import ( "testing" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -11,6 +12,7 @@ import ( k8stesting "k8s.io/client-go/testing" "castai-agent/internal/castai" + mock_version "castai-agent/internal/services/version/mock" ) func TestFilter(t *testing.T) { @@ -40,19 +42,49 @@ func TestFilter(t *testing.T) { } func TestListOpts(t *testing.T) { - expectedRequirements := fields.Requirements{ - { - Field: "reportingComponent", - Operator: selection.Equals, - Value: AutoscalerController, + mockctrl := gomock.NewController(t) + v := mock_version.NewMockInterface(mockctrl) + + tt := map[string]struct { + requirements fields.Requirements + version string + }{ + "has requirements in version == 1.19.0": { + requirements: fields.Requirements{ + { + Field: "reportingComponent", + Operator: selection.Equals, + Value: AutoscalerController, + }, + }, + version: "1.19.0", + }, + "has requirements in version > 1.19.0": { + requirements: fields.Requirements{ + { + Field: "reportingComponent", + Operator: selection.Equals, + Value: AutoscalerController, + }, + }, + version: "1.20.0", + }, + "skips requirements in version < 1.19.0": { + requirements: fields.Requirements{}, + version: "1.18.10", }, } - - opts := metav1.ListOptions{} - ListOpts(&opts) - _, selector, _ := k8stesting.ExtractFromListOptions(opts) - if selector == nil { - selector = fields.Everything() + for name, tc := range tt { + t.Run(name, func(t *testing.T) { + v.EXPECT().Full().Return(tc.version) + opts := metav1.ListOptions{} + ListOpts(&opts, v) + _, selector, _ := k8stesting.ExtractFromListOptions(opts) + if selector == nil { + selector = fields.Everything() + } + require.ElementsMatch(t, tc.requirements, selector.Requirements()) + }) } - require.ElementsMatch(t, expectedRequirements, selector.Requirements()) + } diff --git a/internal/services/controller/handlers/filters/oomevents/filter.go b/internal/services/controller/handlers/filters/oomevents/filter.go index 009f7030..96ac5820 100644 --- a/internal/services/controller/handlers/filters/oomevents/filter.go +++ b/internal/services/controller/handlers/filters/oomevents/filter.go @@ -7,6 +7,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "castai-agent/internal/castai" + "castai-agent/internal/services/version" ) const ( @@ -47,6 +48,6 @@ func Filter(_ castai.EventType, obj interface{}) bool { return strings.Contains(starvedResourcesString, ResourceMemory) } -func ListOpts(opts *metav1.ListOptions) { +func ListOpts(opts *metav1.ListOptions, _ version.Interface) { opts.FieldSelector = fieldSelector } diff --git a/internal/services/controller/handlers/filters/oomevents/filter_test.go b/internal/services/controller/handlers/filters/oomevents/filter_test.go index 93a98ca7..4c906248 100644 --- a/internal/services/controller/handlers/filters/oomevents/filter_test.go +++ b/internal/services/controller/handlers/filters/oomevents/filter_test.go @@ -3,6 +3,7 @@ package oomevents import ( "testing" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -11,6 +12,7 @@ import ( k8stesting "k8s.io/client-go/testing" "castai-agent/internal/castai" + mock_version "castai-agent/internal/services/version/mock" ) func TestFilter(t *testing.T) { @@ -48,6 +50,9 @@ func TestFilter(t *testing.T) { } func TestListOpts(t *testing.T) { + mockctrl := gomock.NewController(t) + v := mock_version.NewMockInterface(mockctrl) + expectedRequirements := fields.Requirements{ { Field: "involvedObject.kind", @@ -62,7 +67,7 @@ func TestListOpts(t *testing.T) { } opts := metav1.ListOptions{} - ListOpts(&opts) + ListOpts(&opts, v) _, selector, _ := k8stesting.ExtractFromListOptions(opts) if selector == nil { selector = fields.Everything()