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

Allow timestamp transformer equalities to be configurable #112158

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -22,6 +22,7 @@ import (
"os"
"reflect"
"strconv"
"sync"
"time"

"k8s.io/apimachinery/pkg/api/equality"
Expand All @@ -33,42 +34,41 @@ import (
"k8s.io/klog/v2"
)

func determineAvoidNoopTimestampUpdatesEnabled() bool {
alexzielenski marked this conversation as resolved.
Show resolved Hide resolved
if avoidNoopTimestampUpdatesString, exists := os.LookupEnv("KUBE_APISERVER_AVOID_NOOP_SSA_TIMESTAMP_UPDATES"); exists {
if ret, err := strconv.ParseBool(avoidNoopTimestampUpdatesString); err == nil {
return ret
} else {
klog.Errorf("failed to parse envar KUBE_APISERVER_AVOID_NOOP_SSA_TIMESTAMP_UPDATES: %v", err)
}
}

// enabled by default
return true
}

var (
avoidNoopTimestampUpdatesEnabled = determineAvoidNoopTimestampUpdatesEnabled()
avoidTimestampEqualities conversion.Equalities
initAvoidTimestampEqualities sync.Once
)

liggitt marked this conversation as resolved.
Show resolved Hide resolved
var avoidTimestampEqualities = func() conversion.Equalities {
var eqs = equality.Semantic.Copy()
func getAvoidTimestampEqualities() conversion.Equalities {
initAvoidTimestampEqualities.Do(func() {
if avoidNoopTimestampUpdatesString, exists := os.LookupEnv("KUBE_APISERVER_AVOID_NOOP_SSA_TIMESTAMP_UPDATES"); exists {
if ret, err := strconv.ParseBool(avoidNoopTimestampUpdatesString); err == nil && !ret {
// leave avoidTimestampEqualities empty.
return
} else {
klog.Errorf("failed to parse envar KUBE_APISERVER_AVOID_NOOP_SSA_TIMESTAMP_UPDATES: %v", err)
}
}

err := eqs.AddFunc(
func(a, b metav1.ManagedFieldsEntry) bool {
// Two objects' managed fields are equivalent if, ignoring timestamp,
// the objects are deeply equal.
a.Time = nil
b.Time = nil
return reflect.DeepEqual(a, b)
},
)
var eqs = equality.Semantic.Copy()
err := eqs.AddFunc(
func(a, b metav1.ManagedFieldsEntry) bool {
// Two objects' managed fields are equivalent if, ignoring timestamp,
// the objects are deeply equal.
a.Time = nil
b.Time = nil
return reflect.DeepEqual(a, b)
},
)

if err != nil {
panic(err)
}
if err != nil {
panic(fmt.Errorf("failed to instantiate semantic equalities: %w", err))
}

return eqs
}()
avoidTimestampEqualities = eqs
})
return avoidTimestampEqualities
}

// IgnoreManagedFieldsTimestampsTransformer reverts timestamp updates
// if the non-managed parts of the object are equivalent
Expand All @@ -77,7 +77,8 @@ func IgnoreManagedFieldsTimestampsTransformer(
newObj runtime.Object,
oldObj runtime.Object,
) (res runtime.Object, err error) {
if !avoidNoopTimestampUpdatesEnabled {
equalities := getAvoidTimestampEqualities()
if len(equalities.Equalities) == 0 {
return newObj, nil
}

Expand Down Expand Up @@ -154,11 +155,11 @@ func IgnoreManagedFieldsTimestampsTransformer(
// This condition ensures the managed fields are always compared first. If
// this check fails, the if statement will short circuit. If the check
// succeeds the slow path is taken which compares entire objects.
if !avoidTimestampEqualities.DeepEqualWithNilDifferentFromEmpty(oldManagedFields, newManagedFields) {
if !equalities.DeepEqualWithNilDifferentFromEmpty(oldManagedFields, newManagedFields) {
return newObj, nil
}

if avoidTimestampEqualities.DeepEqualWithNilDifferentFromEmpty(newObj, oldObj) {
if equalities.DeepEqualWithNilDifferentFromEmpty(newObj, oldObj) {
// Remove any changed timestamps, so that timestamp is not the only
// change seen by etcd.
//
Expand Down