Skip to content

Commit

Permalink
Update To Kubernetes v1.31
Browse files Browse the repository at this point in the history
Signed-off-by: Xabier Larrakoetxea <[email protected]>
  • Loading branch information
slok committed Aug 31, 2024
1 parent be5fe84 commit dc56eef
Show file tree
Hide file tree
Showing 13 changed files with 591 additions and 340 deletions.
45 changes: 45 additions & 0 deletions controller/filter/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package filter

import (
"context"

"k8s.io/apimachinery/pkg/runtime"
)

// UpdatedObjectFilter knows when to ignore an object that has been updated. Ignoring
// an object means that the object will not be processed by the handler.
type UpdatedObjectFilter interface {
// Ignore will ignore the object when returns true.
Ignore(ctx context.Context, old runtime.Object, new runtime.Object) bool
}

// UpdatedObjectFilterFunc is a helper type to create filters wihout the need to declare a new type.
type UpdatedObjectFilterFunc func(ctx context.Context, old runtime.Object, new runtime.Object) bool

func (f UpdatedObjectFilterFunc) Ignore(ctx context.Context, old runtime.Object, new runtime.Object) bool {
return f(ctx, old, new)
}

// NoopUpdatedObjectFilter is a UpdatedObjectFilter that doesn't filter anything.
const NoopUpdatedObjectFilter = noopUpdatedObjectFilter(false)

type noopUpdatedObjectFilter bool

func (noopUpdatedObjectFilter) Ignore(_ context.Context, _ runtime.Object, _ runtime.Object) bool {
return false
}

// NewUpdatedObjectFilterChain is a chain of filters, it will execute all received filters in order
// until a filter returns true, in that moment the execution chain will be stopped and return true.
func NewUpdatedObjectFilterChain(fs ...UpdatedObjectFilter) UpdatedObjectFilter {
return UpdatedObjectFilterFunc(func(ctx context.Context, old, new runtime.Object) bool {
for _, f := range fs {
ignore := f.Ignore(ctx, old, new)
if ignore {
return true
}
}

return false
})
}
81 changes: 81 additions & 0 deletions controller/filter/meta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package filter

import (
"context"
"maps"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)

// AnnotationChangedFilter will ignore the object update if the annotations did not change.
const AnnotationChangedFilter = annotationChangedFilter(false)

type annotationChangedFilter bool

func (annotationChangedFilter) Ignore(ctx context.Context, old runtime.Object, new runtime.Object) bool {
o, n, ok := getMetaV1Object(old, new)
if !ok {
return false
}

return maps.Equal(o.GetAnnotations(), n.GetAnnotations())
}

// LabelChangedFilter will ignore the object update if the labels did not change.
const LabelChangedFilter = labelChangedFilter(false)

type labelChangedFilter bool

func (labelChangedFilter) Ignore(ctx context.Context, old runtime.Object, new runtime.Object) bool {
o, n, ok := getMetaV1Object(old, new)
if !ok {
return false
}

return maps.Equal(o.GetLabels(), n.GetLabels())
}

// GenerationChangedFilter will ignore the object update if the generation did not change.
const GenerationChangedFilter = generationChangedFilter(false)

type generationChangedFilter bool

func (generationChangedFilter) Ignore(ctx context.Context, old runtime.Object, new runtime.Object) bool {
o, n, ok := getMetaV1Object(old, new)
if !ok {
return false
}

return o.GetGeneration() == n.GetGeneration()
}

// ResourceVersionChangedFilter will ignore the object update if the resource version did not change.
const ResourceVersionChangedFilter = resourceVersionChangedFilter(false)

type resourceVersionChangedFilter bool

func (resourceVersionChangedFilter) Ignore(ctx context.Context, old runtime.Object, new runtime.Object) bool {
o, n, ok := getMetaV1Object(old, new)
if !ok {
return false
}

return o.GetResourceVersion() == n.GetResourceVersion()
}

func getMetaV1Object(old runtime.Object, new runtime.Object) (o metav1.Object, n metav1.Object, ok bool) {
if old == nil || new == nil {
return nil, nil, false
}
o, ok = old.(metav1.Object)
if !ok {
return nil, nil, false
}
n, ok = new.(metav1.Object)
if !ok {
return nil, nil, false
}

return o, n, true
}
232 changes: 232 additions & 0 deletions controller/filter/meta_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
package filter_test

import (
"context"
"testing"

"github.com/spotahome/kooper/v2/controller/filter"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)

func TestAnnotationChangedFilter(t *testing.T) {
tests := map[string]struct {
oldObj runtime.Object
newObj runtime.Object
expIgnore bool
}{
"If nil old object, should not ignore.": {
oldObj: nil,
newObj: &corev1.Pod{},
expIgnore: false,
},

"If nil new object, should not ignore.": {
oldObj: &corev1.Pod{},
newObj: nil,
expIgnore: false,
},

"If no valid old object, should not ignore.": {
oldObj: &corev1.PodExecOptions{},
newObj: &corev1.Pod{},
expIgnore: false,
},

"If no valid new object, should not ignore.": {
oldObj: &corev1.Pod{},
newObj: &corev1.PodExecOptions{},
expIgnore: false,
},

"If old and new have different annotations, it should not be ignored.": {
oldObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Annotations: map[string]string{
"k1": "v1",
}}},
newObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Annotations: map[string]string{
"k1": "v2",
}}},
expIgnore: false,
},

"If old and new have same annotations, it should be ignored.": {
oldObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Annotations: map[string]string{
"k1": "v1",
}}},
newObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Annotations: map[string]string{
"k1": "v1",
}}},
expIgnore: true,
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
gotIgnore := filter.AnnotationChangedFilter.Ignore(context.TODO(), test.oldObj, test.newObj)
assert.Equal(t, test.expIgnore, gotIgnore)
})
}
}

func TestLabelChangedFilter(t *testing.T) {
tests := map[string]struct {
oldObj runtime.Object
newObj runtime.Object
expIgnore bool
}{
"If nil old object, should not ignore.": {
oldObj: nil,
newObj: &corev1.Pod{},
expIgnore: false,
},

"If nil new object, should not ignore.": {
oldObj: &corev1.Pod{},
newObj: nil,
expIgnore: false,
},

"If no valid old object, should not ignore.": {
oldObj: &corev1.PodExecOptions{},
newObj: &corev1.Pod{},
expIgnore: false,
},

"If no valid new object, should not ignore.": {
oldObj: &corev1.Pod{},
newObj: &corev1.PodExecOptions{},
expIgnore: false,
},

"If old and new have different labels, it should not be ignored.": {
oldObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Labels: map[string]string{
"k1": "v1",
}}},
newObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Labels: map[string]string{
"k1": "v2",
}}},
expIgnore: false,
},

"If old and new have same labels, it should be ignored.": {
oldObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Labels: map[string]string{
"k1": "v1",
}}},
newObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Labels: map[string]string{
"k1": "v1",
}}},
expIgnore: true,
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
gotIgnore := filter.LabelChangedFilter.Ignore(context.TODO(), test.oldObj, test.newObj)
assert.Equal(t, test.expIgnore, gotIgnore)
})
}
}

func TestGenerationChangedFilter(t *testing.T) {
tests := map[string]struct {
oldObj runtime.Object
newObj runtime.Object
expIgnore bool
}{
"If nil old object, should not ignore.": {
oldObj: nil,
newObj: &corev1.Pod{},
expIgnore: false,
},

"If nil new object, should not ignore.": {
oldObj: &corev1.Pod{},
newObj: nil,
expIgnore: false,
},

"If no valid old object, should not ignore.": {
oldObj: &corev1.PodExecOptions{},
newObj: &corev1.Pod{},
expIgnore: false,
},

"If no valid new object, should not ignore.": {
oldObj: &corev1.Pod{},
newObj: &corev1.PodExecOptions{},
expIgnore: false,
},

"If old and new have different generation, it should not be ignored.": {
oldObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Generation: 42}},
newObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Generation: 43}},
expIgnore: false,
},

"If old and new have same generation, it should be ignored.": {
oldObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Generation: 42}},
newObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{Generation: 42}},
expIgnore: true,
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
gotIgnore := filter.GenerationChangedFilter.Ignore(context.TODO(), test.oldObj, test.newObj)
assert.Equal(t, test.expIgnore, gotIgnore)
})
}
}

func TestResourceVersionChangedFilter(t *testing.T) {
tests := map[string]struct {
oldObj runtime.Object
newObj runtime.Object
expIgnore bool
}{
"If nil old object, should not ignore.": {
oldObj: nil,
newObj: &corev1.Pod{},
expIgnore: false,
},

"If nil new object, should not ignore.": {
oldObj: &corev1.Pod{},
newObj: nil,
expIgnore: false,
},

"If no valid old object, should not ignore.": {
oldObj: &corev1.PodExecOptions{},
newObj: &corev1.Pod{},
expIgnore: false,
},

"If no valid new object, should not ignore.": {
oldObj: &corev1.Pod{},
newObj: &corev1.PodExecOptions{},
expIgnore: false,
},

"If old and new have different resource version, it should not be ignored.": {
oldObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{ResourceVersion: "123456"}},
newObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{ResourceVersion: "123457"}},
expIgnore: false,
},

"If old and new have same resource version, it should be ignored.": {
oldObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{ResourceVersion: "123456"}},
newObj: &corev1.Pod{ObjectMeta: v1.ObjectMeta{ResourceVersion: "123456"}},
expIgnore: true,
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
gotIgnore := filter.ResourceVersionChangedFilter.Ignore(context.TODO(), test.oldObj, test.newObj)
assert.Equal(t, test.expIgnore, gotIgnore)
})
}
}
2 changes: 1 addition & 1 deletion examples/pod-terminator-operator/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

IMAGE_GEN=ghcr.io/slok/kube-code-generator:v0.1.0
IMAGE_GEN=ghcr.io/slok/kube-code-generator:v0.3.1

default: generate

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit dc56eef

Please sign in to comment.