From 3e3276e9fe14bb35262031d5b03f3456a473a22d Mon Sep 17 00:00:00 2001 From: Alay Patel Date: Mon, 4 Nov 2024 14:11:28 -0500 Subject: [PATCH] Promote PodIndexLabel for Statefulset and IndexedJob stable (#128387) * lock feature gate for PodIndexLabel and mark it GA Signed-off-by: Alay Patel * add emulated version if testing disabling of PodIndexLabel FG Signed-off-by: Alay Patel --------- Signed-off-by: Alay Patel --- pkg/controller/job/job_controller_test.go | 5 ++ .../statefulset/stateful_set_control_test.go | 52 +++++++++++++------ pkg/features/versioned_kube_features.go | 1 + .../test_data/versioned_feature_list.yaml | 4 ++ 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/pkg/controller/job/job_controller_test.go b/pkg/controller/job/job_controller_test.go index 6f853957ddd..8cd66c0d1d1 100644 --- a/pkg/controller/job/job_controller_test.go +++ b/pkg/controller/job/job_controller_test.go @@ -38,6 +38,7 @@ import ( "k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" + utilversion "k8s.io/apimachinery/pkg/util/version" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" "k8s.io/apiserver/pkg/util/feature" @@ -1249,6 +1250,10 @@ func TestControllerSyncJob(t *testing.T) { for name, tc := range testCases { t.Run(name, func(t *testing.T) { logger, _ := ktesting.NewTestContext(t) + if tc.podIndexLabelDisabled { + // TODO: this will be removed in 1.35 when 1.31 will fall out of support matrix + featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, feature.DefaultFeatureGate, utilversion.MustParse("1.31")) + } featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.PodIndexLabel, !tc.podIndexLabelDisabled) featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobPodReplacementPolicy, tc.jobPodReplacementPolicy) featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobSuccessPolicy, tc.jobSuccessPolicy) diff --git a/pkg/controller/statefulset/stateful_set_control_test.go b/pkg/controller/statefulset/stateful_set_control_test.go index 27df4e1d7d1..3fc41e1553c 100644 --- a/pkg/controller/statefulset/stateful_set_control_test.go +++ b/pkg/controller/statefulset/stateful_set_control_test.go @@ -39,6 +39,7 @@ import ( "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/intstr" + utilversion "k8s.io/apimachinery/pkg/util/version" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/informers" appsinformers "k8s.io/client-go/informers/apps/v1" @@ -165,7 +166,8 @@ func TestStatefulSetControl(t *testing.T) { fn func(*testing.T, *apps.StatefulSet, invariantFunc) obj func() *apps.StatefulSet }{ - {CreatesPods, simpleSetFn}, + {CreatesPodsWithPodIndexLabelFeature, simpleSetFn}, + {CreatesPodsWithoutPodIndexLabelFeature, simpleSetFn}, {ScalesUp, simpleSetFn}, {ScalesDown, simpleSetFn}, {ReplacesPods, largeSetFn}, @@ -208,7 +210,20 @@ func TestStatefulSetControl(t *testing.T) { } } -func CreatesPods(t *testing.T, set *apps.StatefulSet, invariants invariantFunc) { +func CreatesPodsWithPodIndexLabelFeature(t *testing.T, set *apps.StatefulSet, invariants invariantFunc) { + createPods(t, set, invariants, true) +} + +func CreatesPodsWithoutPodIndexLabelFeature(t *testing.T, set *apps.StatefulSet, invariants invariantFunc) { + createPods(t, set, invariants, false) +} + +func createPods(t *testing.T, set *apps.StatefulSet, invariants invariantFunc, isPodIndexLabelEnabled bool) { + if !isPodIndexLabelEnabled { + // TODO: this will be removed in 1.35 + featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, utilversion.MustParse("1.31")) + } + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodIndexLabel, isPodIndexLabelEnabled) client := fake.NewSimpleClientset(set) om, _, ssc := setupController(client) @@ -229,20 +244,21 @@ func CreatesPods(t *testing.T, set *apps.StatefulSet, invariants invariantFunc) if set.Status.UpdatedReplicas != 3 { t.Error("Failed to set UpdatedReplicas correctly") } + // Check all pods have correct pod index label. - if utilfeature.DefaultFeatureGate.Enabled(features.PodIndexLabel) { - selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector) - if err != nil { - t.Error(err) - } - pods, err := om.podsLister.Pods(set.Namespace).List(selector) - if err != nil { - t.Error(err) - } - if len(pods) != 3 { - t.Errorf("Expected 3 pods, got %d", len(pods)) - } - for _, pod := range pods { + selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector) + if err != nil { + t.Error(err) + } + pods, err := om.podsLister.Pods(set.Namespace).List(selector) + if err != nil { + t.Error(err) + } + if len(pods) != 3 { + t.Errorf("Expected 3 pods, got %d", len(pods)) + } + for _, pod := range pods { + if isPodIndexLabelEnabled { podIndexFromLabel, exists := pod.Labels[apps.PodIndexLabel] if !exists { t.Errorf("Missing pod index label: %s", apps.PodIndexLabel) @@ -252,6 +268,12 @@ func CreatesPods(t *testing.T, set *apps.StatefulSet, invariants invariantFunc) if podIndexFromLabel != podIndexFromName { t.Errorf("Pod index label value (%s) does not match pod index in pod name (%s)", podIndexFromLabel, podIndexFromName) } + } else { + _, exists := pod.Labels[apps.PodIndexLabel] + if exists { + t.Errorf("Pod index label should not exist when feature gate is disabled: %s", apps.PodIndexLabel) + continue + } } } } diff --git a/pkg/features/versioned_kube_features.go b/pkg/features/versioned_kube_features.go index 7b2ec852ee6..e6477662d1d 100644 --- a/pkg/features/versioned_kube_features.go +++ b/pkg/features/versioned_kube_features.go @@ -559,6 +559,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate PodIndexLabel: { {Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Beta}, + {Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.35 }, PodLifecycleSleepAction: { diff --git a/test/featuregates_linter/test_data/versioned_feature_list.yaml b/test/featuregates_linter/test_data/versioned_feature_list.yaml index f69f2b99a23..2317a921630 100644 --- a/test/featuregates_linter/test_data/versioned_feature_list.yaml +++ b/test/featuregates_linter/test_data/versioned_feature_list.yaml @@ -884,6 +884,10 @@ lockToDefault: false preRelease: Beta version: "1.28" + - default: true + lockToDefault: true + preRelease: GA + version: "1.32" - name: PodLifecycleSleepAction versionedSpecs: - default: false