diff --git a/features/envvar.go b/features/envvar.go index d67c2adc9..93aa21fa7 100644 --- a/features/envvar.go +++ b/features/envvar.go @@ -157,6 +157,13 @@ func (f *envVarFeatureGates) set(featureName Feature, featureValue bool, allowCh // read from the corresponding environmental variable. func (f *envVarFeatureGates) getEnabledMapFromEnvVar() map[Feature]bool { f.readEnvVarsOnce.Do(func() { + // This code does not really support contextual logging. Making it do so has huge + // implications for several call chains because the Enabled call then needs + // a `*WithLogger` variant. This does not matter in Kubernetes itself because + // all Kubernetes components replace the feature gate implementation used + // by client-go, but it might matter elsewhere. + logger := klog.Background() + featureGatesState := map[Feature]bool{} for feature, featureSpec := range f.known { featureState, featureStateSet := os.LookupEnv(fmt.Sprintf("KUBE_FEATURE_%s", feature)) @@ -166,10 +173,10 @@ func (f *envVarFeatureGates) getEnabledMapFromEnvVar() map[Feature]bool { boolVal, boolErr := strconv.ParseBool(featureState) switch { case boolErr != nil: - utilruntime.HandleError(fmt.Errorf("cannot set feature gate %q to %q, due to %v", feature, featureState, boolErr)) + utilruntime.HandleErrorWithLogger(logger, boolErr, "Could not set feature gate", "feature", feature, "desiredState", featureState) case featureSpec.LockToDefault: if boolVal != featureSpec.Default { - utilruntime.HandleError(fmt.Errorf("cannot set feature gate %q to %q, feature is locked to %v", feature, featureState, featureSpec.Default)) + utilruntime.HandleErrorWithLogger(logger, nil, "Could not set feature gate, feature is locked", "feature", feature, "desiredState", featureState, "lockedState", featureSpec.Default) break } featureGatesState[feature] = featureSpec.Default @@ -182,10 +189,10 @@ func (f *envVarFeatureGates) getEnabledMapFromEnvVar() map[Feature]bool { for feature, featureSpec := range f.known { if featureState, ok := featureGatesState[feature]; ok { - klog.V(1).InfoS("Feature gate updated state", "feature", feature, "enabled", featureState) + logger.V(1).Info("Feature gate updated state", "feature", feature, "enabled", featureState) continue } - klog.V(1).InfoS("Feature gate default state", "feature", feature, "enabled", featureSpec.Default) + logger.V(1).Info("Feature gate default state", "feature", feature, "enabled", featureSpec.Default) } }) return f.enabledViaEnvVar.Load().(map[Feature]bool) diff --git a/features/features.go b/features/features.go index cabb7468d..f21511dca 100644 --- a/features/features.go +++ b/features/features.go @@ -17,7 +17,7 @@ limitations under the License. package features import ( - "errors" + "context" "sync/atomic" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -127,7 +127,9 @@ func AddVersionedFeaturesToExistingFeatureGates(registry VersionedRegistry) erro // clientgofeaturegate.ReplaceFeatureGates(utilfeature.DefaultMutableFeatureGate) func ReplaceFeatureGates(newFeatureGates Gates) { if replaceFeatureGatesWithWarningIndicator(newFeatureGates) { - utilruntime.HandleError(errors.New("the default feature gates implementation has already been used and now it's being overwritten. This might lead to unexpected behaviour. Check your initialization order")) + // TODO (?): A new API would be needed where callers pass in a context or logger. + // Probably not worth it. + utilruntime.HandleErrorWithContext(context.TODO(), nil, "The default feature gates implementation has already been used and now it's being overwritten. This might lead to unexpected behaviour. Check your initialization order.") } } diff --git a/go.mod b/go.mod index afd397034..d357da974 100644 --- a/go.mod +++ b/go.mod @@ -23,8 +23,8 @@ require ( golang.org/x/time v0.14.0 google.golang.org/protobuf v1.36.11 gopkg.in/evanphx/json-patch.v4 v4.13.0 - k8s.io/api v0.0.0-20260221190738-2b63a8ab844a - k8s.io/apimachinery v0.0.0-20260220060104-eae5e9edd982 + k8s.io/api v0.0.0-20260225113016-5bcacdeb1fa7 + k8s.io/apimachinery v0.0.0-20260224233333-db8f40c74cff k8s.io/klog/v2 v2.130.1 k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 diff --git a/go.sum b/go.sum index f304da53b..329b722f7 100644 --- a/go.sum +++ b/go.sum @@ -123,10 +123,10 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.0.0-20260221190738-2b63a8ab844a h1:e59cK8pukhrWQv/WNLTP6A4SxZ1slCJMJ3Bz2MD2lzc= -k8s.io/api v0.0.0-20260221190738-2b63a8ab844a/go.mod h1:Paz4p8MttOpc/UbURW4kl71XIux9Mz5ILeBThkmukWw= -k8s.io/apimachinery v0.0.0-20260220060104-eae5e9edd982 h1:B21Y+/NS0BgH5O47QjvSQI4NT4Gx7XH22DRrktWK6aw= -k8s.io/apimachinery v0.0.0-20260220060104-eae5e9edd982/go.mod h1:7mgr/dli8ofwAbcIQXetFVX1fbOYsOYojq3AUbybVmQ= +k8s.io/api v0.0.0-20260225113016-5bcacdeb1fa7 h1:sLZeXdnm4IBamL+Q0YIi3aLjOZeU6XSPAyq+llItk7U= +k8s.io/api v0.0.0-20260225113016-5bcacdeb1fa7/go.mod h1:sJfdY4gzHfS5ewdEw0CVoyPe9x4YLhHe2eZHXiaegXo= +k8s.io/apimachinery v0.0.0-20260224233333-db8f40c74cff h1:yJisc9AAvRi0Y6BdNqnjR/KlY298LeFUFI+YOmqpbUw= +k8s.io/apimachinery v0.0.0-20260224233333-db8f40c74cff/go.mod h1:7mgr/dli8ofwAbcIQXetFVX1fbOYsOYojq3AUbybVmQ= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 h1:HhDfevmPS+OalTjQRKbTHppRIz01AWi8s45TMXStgYY=