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

fix: disable event field selector on Kubernetes versions < 1.19.0 #149

Merged
merged 1 commit into from
Dec 6, 2023
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
10 changes: 6 additions & 4 deletions internal/services/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
{
Expand All @@ -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{
{
Expand Down Expand Up @@ -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)
})
})
}

Expand Down
2 changes: 1 addition & 1 deletion internal/services/controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ 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 (
AutoscalerController = "autoscaler.cast.ai"
fieldSelector = "reportingComponent=" + AutoscalerController
)

var minFieldSelectorVersion = k8sversion.MustParseSemantic("1.19.0")

func Filter(_ castai.EventType, obj interface{}) bool {
event, ok := obj.(*corev1.Event)
if !ok {
Expand All @@ -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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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) {
Expand Down Expand Up @@ -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())

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"castai-agent/internal/castai"
"castai-agent/internal/services/version"
)

const (
Expand Down Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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) {
Expand Down Expand Up @@ -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",
Expand All @@ -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()
Expand Down