diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 4c2939fff7a..2596c6a5650 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -9629,11 +9629,11 @@ "type": "boolean" }, "serving": { - "description": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + "description": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition.", "type": "boolean" }, "terminating": { - "description": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + "description": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating.", "type": "boolean" } }, diff --git a/api/openapi-spec/v3/apis__discovery.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__discovery.k8s.io__v1_openapi.json index 381233bb3f5..73f1cd07585 100644 --- a/api/openapi-spec/v3/apis__discovery.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__discovery.k8s.io__v1_openapi.json @@ -107,11 +107,11 @@ "type": "boolean" }, "serving": { - "description": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + "description": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition.", "type": "boolean" }, "terminating": { - "description": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + "description": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating.", "type": "boolean" } }, diff --git a/pkg/apis/discovery/types.go b/pkg/apis/discovery/types.go index f308eefe100..8b4dc265a60 100644 --- a/pkg/apis/discovery/types.go +++ b/pkg/apis/discovery/types.go @@ -118,15 +118,13 @@ type EndpointConditions struct { // serving is identical to ready except that it is set regardless of the // terminating state of endpoints. This condition should be set to true for // a ready endpoint that is terminating. If nil, consumers should defer to - // the ready condition. This field can be enabled with the - // EndpointSliceTerminatingCondition feature gate. + // the ready condition. // +optional Serving *bool // terminating indicates that this endpoint is terminating. A nil value // indicates an unknown state. Consumers should interpret this unknown state - // to mean that the endpoint is not terminating. This field can be enabled - // with the EndpointSliceTerminatingCondition feature gate. + // to mean that the endpoint is not terminating. // +optional Terminating *bool } diff --git a/pkg/controller/endpointslice/endpointslice_controller_test.go b/pkg/controller/endpointslice/endpointslice_controller_test.go index 589fc642d7b..aaf933e685b 100644 --- a/pkg/controller/endpointslice/endpointslice_controller_test.go +++ b/pkg/controller/endpointslice/endpointslice_controller_test.go @@ -35,17 +35,14 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/wait" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes/fake" k8stesting "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" - featuregatetesting "k8s.io/component-base/featuregate/testing" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller/endpointslice/topologycache" endpointutil "k8s.io/kubernetes/pkg/controller/util/endpoint" endpointsliceutil "k8s.io/kubernetes/pkg/controller/util/endpointslice" - "k8s.io/kubernetes/pkg/features" utilpointer "k8s.io/utils/pointer" ) @@ -418,12 +415,11 @@ func TestSyncService(t *testing.T) { deletionTimestamp := metav1.Now() testcases := []struct { - name string - service *v1.Service - pods []*v1.Pod - expectedEndpointPorts []discovery.EndpointPort - expectedEndpoints []discovery.Endpoint - terminatingGateEnabled bool + name string + service *v1.Service + pods []*v1.Pod + expectedEndpointPorts []discovery.EndpointPort + expectedEndpoints []discovery.Endpoint }{ { name: "pods with multiple IPs and Service with ipFamilies=ipv4", @@ -522,7 +518,9 @@ func TestSyncService(t *testing.T) { expectedEndpoints: []discovery.Endpoint{ { Conditions: discovery.EndpointConditions{ - Ready: utilpointer.BoolPtr(true), + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), }, Addresses: []string{"10.0.0.1"}, TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod0"}, @@ -530,7 +528,9 @@ func TestSyncService(t *testing.T) { }, { Conditions: discovery.EndpointConditions{ - Ready: utilpointer.BoolPtr(true), + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), }, Addresses: []string{"10.0.0.2"}, TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod1"}, @@ -635,7 +635,9 @@ func TestSyncService(t *testing.T) { expectedEndpoints: []discovery.Endpoint{ { Conditions: discovery.EndpointConditions{ - Ready: utilpointer.BoolPtr(true), + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), }, Addresses: []string{"fd08::5678:0000:0000:9abc:def0"}, TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod1"}, @@ -644,7 +646,7 @@ func TestSyncService(t *testing.T) { }, }, { - name: "Terminating pods with EndpointSliceTerminatingCondition enabled", + name: "Terminating pods", service: &v1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: "foobar", @@ -757,114 +759,9 @@ func TestSyncService(t *testing.T) { NodeName: utilpointer.StringPtr("node-1"), }, }, - terminatingGateEnabled: true, }, { - name: "Terminating pods with EndpointSliceTerminatingCondition disabled", - service: &v1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foobar", - Namespace: "default", - CreationTimestamp: creationTimestamp, - }, - Spec: v1.ServiceSpec{ - Ports: []v1.ServicePort{ - {Name: "tcp-example", TargetPort: intstr.FromInt(80), Protocol: v1.ProtocolTCP}, - {Name: "udp-example", TargetPort: intstr.FromInt(161), Protocol: v1.ProtocolUDP}, - {Name: "sctp-example", TargetPort: intstr.FromInt(3456), Protocol: v1.ProtocolSCTP}, - }, - Selector: map[string]string{"foo": "bar"}, - IPFamilies: []v1.IPFamily{v1.IPv4Protocol}, - }, - }, - pods: []*v1.Pod{ - { - // one ready pod for comparison - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "pod0", - Labels: map[string]string{"foo": "bar"}, - DeletionTimestamp: nil, - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{{ - Name: "container-1", - }}, - NodeName: "node-1", - }, - Status: v1.PodStatus{ - PodIP: "10.0.0.1", - PodIPs: []v1.PodIP{{ - IP: "10.0.0.1", - }}, - Conditions: []v1.PodCondition{ - { - Type: v1.PodReady, - Status: v1.ConditionTrue, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "pod1", - Labels: map[string]string{"foo": "bar"}, - DeletionTimestamp: &deletionTimestamp, - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{{ - Name: "container-1", - }}, - NodeName: "node-1", - }, - Status: v1.PodStatus{ - PodIP: "10.0.0.2", - PodIPs: []v1.PodIP{ - { - IP: "10.0.0.2", - }, - }, - Conditions: []v1.PodCondition{ - { - Type: v1.PodReady, - Status: v1.ConditionTrue, - }, - }, - }, - }, - }, - expectedEndpointPorts: []discovery.EndpointPort{ - { - Name: utilpointer.StringPtr("sctp-example"), - Protocol: protoPtr(v1.ProtocolSCTP), - Port: utilpointer.Int32Ptr(int32(3456)), - }, - { - Name: utilpointer.StringPtr("udp-example"), - Protocol: protoPtr(v1.ProtocolUDP), - Port: utilpointer.Int32Ptr(int32(161)), - }, - { - Name: utilpointer.StringPtr("tcp-example"), - Protocol: protoPtr(v1.ProtocolTCP), - Port: utilpointer.Int32Ptr(int32(80)), - }, - }, - expectedEndpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Ready: utilpointer.BoolPtr(true), - }, - Addresses: []string{"10.0.0.1"}, - TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod0"}, - NodeName: utilpointer.StringPtr("node-1"), - }, - }, - terminatingGateEnabled: false, - }, - { - name: "Not ready terminating pods with EndpointSliceTerminatingCondition enabled", + name: "Not ready terminating pods", service: &v1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: "foobar", @@ -977,118 +874,11 @@ func TestSyncService(t *testing.T) { NodeName: utilpointer.StringPtr("node-1"), }, }, - terminatingGateEnabled: true, - }, - { - name: "Not ready terminating pods with EndpointSliceTerminatingCondition disabled", - service: &v1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foobar", - Namespace: "default", - CreationTimestamp: creationTimestamp, - }, - Spec: v1.ServiceSpec{ - Ports: []v1.ServicePort{ - {Name: "tcp-example", TargetPort: intstr.FromInt(80), Protocol: v1.ProtocolTCP}, - {Name: "udp-example", TargetPort: intstr.FromInt(161), Protocol: v1.ProtocolUDP}, - {Name: "sctp-example", TargetPort: intstr.FromInt(3456), Protocol: v1.ProtocolSCTP}, - }, - Selector: map[string]string{"foo": "bar"}, - IPFamilies: []v1.IPFamily{v1.IPv4Protocol}, - }, - }, - pods: []*v1.Pod{ - { - // one ready pod for comparison - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "pod0", - Labels: map[string]string{"foo": "bar"}, - DeletionTimestamp: nil, - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{{ - Name: "container-1", - }}, - NodeName: "node-1", - }, - Status: v1.PodStatus{ - PodIP: "10.0.0.1", - PodIPs: []v1.PodIP{{ - IP: "10.0.0.1", - }}, - Conditions: []v1.PodCondition{ - { - Type: v1.PodReady, - Status: v1.ConditionTrue, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "pod1", - Labels: map[string]string{"foo": "bar"}, - DeletionTimestamp: &deletionTimestamp, - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{{ - Name: "container-1", - }}, - NodeName: "node-1", - }, - Status: v1.PodStatus{ - PodIP: "10.0.0.2", - PodIPs: []v1.PodIP{ - { - IP: "10.0.0.2", - }, - }, - Conditions: []v1.PodCondition{ - { - Type: v1.PodReady, - Status: v1.ConditionFalse, - }, - }, - }, - }, - }, - expectedEndpointPorts: []discovery.EndpointPort{ - { - Name: utilpointer.StringPtr("sctp-example"), - Protocol: protoPtr(v1.ProtocolSCTP), - Port: utilpointer.Int32Ptr(int32(3456)), - }, - { - Name: utilpointer.StringPtr("udp-example"), - Protocol: protoPtr(v1.ProtocolUDP), - Port: utilpointer.Int32Ptr(int32(161)), - }, - { - Name: utilpointer.StringPtr("tcp-example"), - Protocol: protoPtr(v1.ProtocolTCP), - Port: utilpointer.Int32Ptr(int32(80)), - }, - }, - expectedEndpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Ready: utilpointer.BoolPtr(true), - }, - Addresses: []string{"10.0.0.1"}, - TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod0"}, - NodeName: utilpointer.StringPtr("node-1"), - }, - }, - terminatingGateEnabled: false, }, } for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testcase.terminatingGateEnabled)() - client, esController := newController([]string{"node-1"}, time.Duration(0)) for _, pod := range testcase.pods { diff --git a/pkg/controller/endpointslice/reconciler.go b/pkg/controller/endpointslice/reconciler.go index 160fca2bf3c..f97d3ccf43d 100644 --- a/pkg/controller/endpointslice/reconciler.go +++ b/pkg/controller/endpointslice/reconciler.go @@ -30,7 +30,6 @@ import ( "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" - utilfeature "k8s.io/apiserver/pkg/util/feature" clientset "k8s.io/client-go/kubernetes" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/klog/v2" @@ -38,7 +37,6 @@ import ( "k8s.io/kubernetes/pkg/controller/endpointslice/topologycache" endpointutil "k8s.io/kubernetes/pkg/controller/util/endpoint" endpointsliceutil "k8s.io/kubernetes/pkg/controller/util/endpointslice" - "k8s.io/kubernetes/pkg/features" ) // reconciler is responsible for transforming current EndpointSlice state into @@ -154,8 +152,7 @@ func (r *reconciler) reconcileByAddressType(service *corev1.Service, pods []*cor desiredEndpointsByPortMap := map[endpointutil.PortMapKey]endpointsliceutil.EndpointSet{} for _, pod := range pods { - includeTerminating := service.Spec.PublishNotReadyAddresses || utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceTerminatingCondition) - if !endpointutil.ShouldPodBeInEndpoints(pod, includeTerminating) { + if !endpointutil.ShouldPodBeInEndpoints(pod, true) { continue } diff --git a/pkg/controller/endpointslice/reconciler_test.go b/pkg/controller/endpointslice/reconciler_test.go index ff5f99abe2e..c2db2fe18f9 100644 --- a/pkg/controller/endpointslice/reconciler_test.go +++ b/pkg/controller/endpointslice/reconciler_test.go @@ -32,18 +32,15 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes/fake" corelisters "k8s.io/client-go/listers/core/v1" k8stesting "k8s.io/client-go/testing" - featuregatetesting "k8s.io/component-base/featuregate/testing" "k8s.io/component-base/metrics/testutil" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller/endpointslice/metrics" "k8s.io/kubernetes/pkg/controller/endpointslice/topologycache" endpointsliceutil "k8s.io/kubernetes/pkg/controller/util/endpointslice" - "k8s.io/kubernetes/pkg/features" utilpointer "k8s.io/utils/pointer" ) @@ -119,17 +116,20 @@ func TestReconcile1Pod(t *testing.T) { expectedEndpoint discovery.Endpoint expectedLabels map[string]string expectedEndpointPerSlice map[discovery.AddressType][]discovery.Endpoint - terminatingGateEnabled bool }{ "no-family-service": { service: noFamilyService, expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{ discovery.AddressTypeIPv4: { { - Addresses: []string{"1.2.3.4"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), + Addresses: []string{"1.2.3.4"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), TargetRef: &corev1.ObjectReference{ Kind: "Pod", Namespace: namespace, @@ -144,29 +144,6 @@ func TestReconcile1Pod(t *testing.T) { }, }, "ipv4": { - service: svcv4, - expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{ - discovery.AddressTypeIPv4: { - { - Addresses: []string{"1.2.3.4"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), - TargetRef: &corev1.ObjectReference{ - Kind: "Pod", - Namespace: namespace, - Name: "pod1", - }, - }, - }, - }, - expectedLabels: map[string]string{ - discovery.LabelManagedBy: controllerName, - discovery.LabelServiceName: "foo", - corev1.IsHeadlessService: "", - }, - }, - "ipv4-with-terminating-gate-enabled": { service: svcv4, expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{ discovery.AddressTypeIPv4: { @@ -192,17 +169,20 @@ func TestReconcile1Pod(t *testing.T) { discovery.LabelServiceName: "foo", corev1.IsHeadlessService: "", }, - terminatingGateEnabled: true, }, "ipv4-clusterip": { service: svcv4ClusterIP, expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{ discovery.AddressTypeIPv4: { { - Addresses: []string{"1.2.3.4"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), + Addresses: []string{"1.2.3.4"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), TargetRef: &corev1.ObjectReference{ Kind: "Pod", Namespace: namespace, @@ -213,10 +193,14 @@ func TestReconcile1Pod(t *testing.T) { }, expectedAddressType: discovery.AddressTypeIPv4, expectedEndpoint: discovery.Endpoint{ - Addresses: []string{"1.2.3.4"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), + Addresses: []string{"1.2.3.4"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), TargetRef: &corev1.ObjectReference{ Kind: "Pod", Namespace: namespace, @@ -233,10 +217,14 @@ func TestReconcile1Pod(t *testing.T) { expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{ discovery.AddressTypeIPv4: { { - Addresses: []string{"1.2.3.4"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), + Addresses: []string{"1.2.3.4"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), TargetRef: &corev1.ObjectReference{ Kind: "Pod", Namespace: namespace, @@ -247,10 +235,14 @@ func TestReconcile1Pod(t *testing.T) { }, expectedAddressType: discovery.AddressTypeIPv4, expectedEndpoint: discovery.Endpoint{ - Addresses: []string{"1.2.3.4"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), + Addresses: []string{"1.2.3.4"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), TargetRef: &corev1.ObjectReference{ Kind: "Pod", Namespace: namespace, @@ -269,10 +261,14 @@ func TestReconcile1Pod(t *testing.T) { expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{ discovery.AddressTypeIPv4: { { - Addresses: []string{"1.2.3.4"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), + Addresses: []string{"1.2.3.4"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), TargetRef: &corev1.ObjectReference{ Kind: "Pod", Namespace: namespace, @@ -283,10 +279,14 @@ func TestReconcile1Pod(t *testing.T) { }, expectedAddressType: discovery.AddressTypeIPv4, expectedEndpoint: discovery.Endpoint{ - Addresses: []string{"1.2.3.4"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), + Addresses: []string{"1.2.3.4"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), TargetRef: &corev1.ObjectReference{ Kind: "Pod", Namespace: namespace, @@ -305,10 +305,14 @@ func TestReconcile1Pod(t *testing.T) { expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{ discovery.AddressTypeIPv6: { { - Addresses: []string{"1234::5678:0000:0000:9abc:def0"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), + Addresses: []string{"1234::5678:0000:0000:9abc:def0"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), TargetRef: &corev1.ObjectReference{ Kind: "Pod", Namespace: namespace, @@ -329,10 +333,14 @@ func TestReconcile1Pod(t *testing.T) { expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{ discovery.AddressTypeIPv6: { { - Addresses: []string{"1234::5678:0000:0000:9abc:def0"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), + Addresses: []string{"1234::5678:0000:0000:9abc:def0"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), TargetRef: &corev1.ObjectReference{ Kind: "Pod", Namespace: namespace, @@ -352,10 +360,14 @@ func TestReconcile1Pod(t *testing.T) { expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{ discovery.AddressTypeIPv6: { { - Addresses: []string{"1234::5678:0000:0000:9abc:def0"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), + Addresses: []string{"1234::5678:0000:0000:9abc:def0"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), TargetRef: &corev1.ObjectReference{ Kind: "Pod", Namespace: namespace, @@ -365,10 +377,14 @@ func TestReconcile1Pod(t *testing.T) { }, discovery.AddressTypeIPv4: { { - Addresses: []string{"1.2.3.4"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), + Addresses: []string{"1.2.3.4"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), TargetRef: &corev1.ObjectReference{ Kind: "Pod", Namespace: namespace, @@ -386,8 +402,6 @@ func TestReconcile1Pod(t *testing.T) { for name, testCase := range testCases { t.Run(name, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testCase.terminatingGateEnabled)() - client := newClientset() setupMetrics() triggerTime := time.Now().UTC() diff --git a/pkg/controller/endpointslice/utils.go b/pkg/controller/endpointslice/utils.go index 742427a0289..448ae9fb347 100644 --- a/pkg/controller/endpointslice/utils.go +++ b/pkg/controller/endpointslice/utils.go @@ -20,14 +20,13 @@ import ( "fmt" "time" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" discovery "k8s.io/api/discovery/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/sets" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" podutil "k8s.io/kubernetes/pkg/api/v1/pod" @@ -35,7 +34,6 @@ import ( "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/apis/discovery/validation" endpointutil "k8s.io/kubernetes/pkg/controller/util/endpoint" - "k8s.io/kubernetes/pkg/features" utilnet "k8s.io/utils/net" ) @@ -49,7 +47,9 @@ func podToEndpoint(pod *v1.Pod, node *v1.Node, service *v1.Service, addressType ep := discovery.Endpoint{ Addresses: getEndpointAddresses(pod.Status, service, addressType), Conditions: discovery.EndpointConditions{ - Ready: &ready, + Ready: &ready, + Serving: &serving, + Terminating: &terminating, }, TargetRef: &v1.ObjectReference{ Kind: "Pod", @@ -59,11 +59,6 @@ func podToEndpoint(pod *v1.Pod, node *v1.Node, service *v1.Service, addressType }, } - if utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceTerminatingCondition) { - ep.Conditions.Serving = &serving - ep.Conditions.Terminating = &terminating - } - if pod.Spec.NodeName != "" { ep.NodeName = &pod.Spec.NodeName } diff --git a/pkg/controller/endpointslice/utils_test.go b/pkg/controller/endpointslice/utils_test.go index 22c70964891..ee96ec9b077 100644 --- a/pkg/controller/endpointslice/utils_test.go +++ b/pkg/controller/endpointslice/utils_test.go @@ -31,11 +31,8 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/rand" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/kubernetes/fake" k8stesting "k8s.io/client-go/testing" - featuregatetesting "k8s.io/component-base/featuregate/testing" - "k8s.io/kubernetes/pkg/features" utilpointer "k8s.io/utils/pointer" ) @@ -251,131 +248,11 @@ func TestPodToEndpoint(t *testing.T) { svc *v1.Service expectedEndpoint discovery.Endpoint publishNotReadyAddresses bool - terminatingGateEnabled bool }{ { name: "Ready pod", pod: readyPod, svc: &svc, - expectedEndpoint: discovery.Endpoint{ - Addresses: []string{"1.2.3.5"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - NodeName: utilpointer.StringPtr("node-1"), - TargetRef: &v1.ObjectReference{ - Kind: "Pod", - Namespace: ns, - Name: readyPod.Name, - UID: readyPod.UID, - }, - }, - }, - { - name: "Ready pod + publishNotReadyAddresses", - pod: readyPod, - svc: &svcPublishNotReady, - expectedEndpoint: discovery.Endpoint{ - Addresses: []string{"1.2.3.5"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - NodeName: utilpointer.StringPtr("node-1"), - TargetRef: &v1.ObjectReference{ - Kind: "Pod", - Namespace: ns, - Name: readyPod.Name, - UID: readyPod.UID, - }, - }, - }, - { - name: "Unready pod", - pod: unreadyPod, - svc: &svc, - expectedEndpoint: discovery.Endpoint{ - Addresses: []string{"1.2.3.5"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(false)}, - NodeName: utilpointer.StringPtr("node-1"), - TargetRef: &v1.ObjectReference{ - Kind: "Pod", - Namespace: ns, - Name: readyPod.Name, - UID: readyPod.UID, - }, - }, - }, - { - name: "Unready pod + publishNotReadyAddresses", - pod: unreadyPod, - svc: &svcPublishNotReady, - expectedEndpoint: discovery.Endpoint{ - Addresses: []string{"1.2.3.5"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - NodeName: utilpointer.StringPtr("node-1"), - TargetRef: &v1.ObjectReference{ - Kind: "Pod", - Namespace: ns, - Name: readyPod.Name, - UID: readyPod.UID, - }, - }, - }, - { - name: "Ready pod + node labels", - pod: readyPod, - node: node1, - svc: &svc, - expectedEndpoint: discovery.Endpoint{ - Addresses: []string{"1.2.3.5"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), - TargetRef: &v1.ObjectReference{ - Kind: "Pod", - Namespace: ns, - Name: readyPod.Name, - UID: readyPod.UID, - }, - }, - }, - { - name: "Multi IP Ready pod + node labels", - pod: multiIPPod, - node: node1, - svc: &svc, - expectedEndpoint: discovery.Endpoint{ - Addresses: []string{"1.2.3.4"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), - TargetRef: &v1.ObjectReference{ - Kind: "Pod", - Namespace: ns, - Name: readyPod.Name, - UID: readyPod.UID, - }, - }, - }, - { - name: "Ready pod + hostname", - pod: readyPodHostname, - node: node1, - svc: &svc, - expectedEndpoint: discovery.Endpoint{ - Addresses: []string{"1.2.3.5"}, - Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, - Hostname: &readyPodHostname.Spec.Hostname, - Zone: utilpointer.StringPtr("us-central1-a"), - NodeName: utilpointer.StringPtr("node-1"), - TargetRef: &v1.ObjectReference{ - Kind: "Pod", - Namespace: ns, - Name: readyPodHostname.Name, - UID: readyPodHostname.UID, - }, - }, - }, - { - name: "Ready pod, terminating gate enabled", - pod: readyPod, - svc: &svc, expectedEndpoint: discovery.Endpoint{ Addresses: []string{"1.2.3.5"}, Conditions: discovery.EndpointConditions{ @@ -391,16 +268,17 @@ func TestPodToEndpoint(t *testing.T) { UID: readyPod.UID, }, }, - terminatingGateEnabled: true, }, { - name: "Ready terminating pod, terminating gate disabled", - pod: readyTerminatingPod, - svc: &svc, + name: "Ready pod + publishNotReadyAddresses", + pod: readyPod, + svc: &svcPublishNotReady, expectedEndpoint: discovery.Endpoint{ Addresses: []string{"1.2.3.5"}, Conditions: discovery.EndpointConditions{ - Ready: utilpointer.BoolPtr(false), + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), }, NodeName: utilpointer.StringPtr("node-1"), TargetRef: &v1.ObjectReference{ @@ -410,10 +288,136 @@ func TestPodToEndpoint(t *testing.T) { UID: readyPod.UID, }, }, - terminatingGateEnabled: false, }, { - name: "Ready terminating pod, terminating gate enabled", + name: "Unready pod", + pod: unreadyPod, + svc: &svc, + expectedEndpoint: discovery.Endpoint{ + Addresses: []string{"1.2.3.5"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(false), + Serving: utilpointer.BoolPtr(false), + Terminating: utilpointer.BoolPtr(false), + }, + NodeName: utilpointer.StringPtr("node-1"), + TargetRef: &v1.ObjectReference{ + Kind: "Pod", + Namespace: ns, + Name: readyPod.Name, + UID: readyPod.UID, + }, + }, + }, + { + name: "Unready pod + publishNotReadyAddresses", + pod: unreadyPod, + svc: &svcPublishNotReady, + expectedEndpoint: discovery.Endpoint{ + Addresses: []string{"1.2.3.5"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(false), + Terminating: utilpointer.BoolPtr(false), + }, + NodeName: utilpointer.StringPtr("node-1"), + TargetRef: &v1.ObjectReference{ + Kind: "Pod", + Namespace: ns, + Name: readyPod.Name, + UID: readyPod.UID, + }, + }, + }, + { + name: "Ready pod + node labels", + pod: readyPod, + node: node1, + svc: &svc, + expectedEndpoint: discovery.Endpoint{ + Addresses: []string{"1.2.3.5"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), + TargetRef: &v1.ObjectReference{ + Kind: "Pod", + Namespace: ns, + Name: readyPod.Name, + UID: readyPod.UID, + }, + }, + }, + { + name: "Multi IP Ready pod + node labels", + pod: multiIPPod, + node: node1, + svc: &svc, + expectedEndpoint: discovery.Endpoint{ + Addresses: []string{"1.2.3.4"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), + TargetRef: &v1.ObjectReference{ + Kind: "Pod", + Namespace: ns, + Name: readyPod.Name, + UID: readyPod.UID, + }, + }, + }, + { + name: "Ready pod + hostname", + pod: readyPodHostname, + node: node1, + svc: &svc, + expectedEndpoint: discovery.Endpoint{ + Addresses: []string{"1.2.3.5"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + Hostname: &readyPodHostname.Spec.Hostname, + Zone: utilpointer.StringPtr("us-central1-a"), + NodeName: utilpointer.StringPtr("node-1"), + TargetRef: &v1.ObjectReference{ + Kind: "Pod", + Namespace: ns, + Name: readyPodHostname.Name, + UID: readyPodHostname.UID, + }, + }, + }, + { + name: "Ready pod", + pod: readyPod, + svc: &svc, + expectedEndpoint: discovery.Endpoint{ + Addresses: []string{"1.2.3.5"}, + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + Serving: utilpointer.BoolPtr(true), + Terminating: utilpointer.BoolPtr(false), + }, + NodeName: utilpointer.StringPtr("node-1"), + TargetRef: &v1.ObjectReference{ + Kind: "Pod", + Namespace: ns, + Name: readyPod.Name, + UID: readyPod.UID, + }, + }, + }, + { + name: "Ready terminating pod", pod: readyTerminatingPod, svc: &svc, expectedEndpoint: discovery.Endpoint{ @@ -431,29 +435,9 @@ func TestPodToEndpoint(t *testing.T) { UID: readyPod.UID, }, }, - terminatingGateEnabled: true, }, { - name: "Not ready terminating pod, terminating gate disabled", - pod: unreadyTerminatingPod, - svc: &svc, - expectedEndpoint: discovery.Endpoint{ - Addresses: []string{"1.2.3.5"}, - Conditions: discovery.EndpointConditions{ - Ready: utilpointer.BoolPtr(false), - }, - NodeName: utilpointer.StringPtr("node-1"), - TargetRef: &v1.ObjectReference{ - Kind: "Pod", - Namespace: ns, - Name: readyPod.Name, - UID: readyPod.UID, - }, - }, - terminatingGateEnabled: false, - }, - { - name: "Not ready terminating pod, terminating gate enabled", + name: "Not ready terminating pod", pod: unreadyTerminatingPod, svc: &svc, expectedEndpoint: discovery.Endpoint{ @@ -471,14 +455,11 @@ func TestPodToEndpoint(t *testing.T) { UID: readyPod.UID, }, }, - terminatingGateEnabled: true, }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testCase.terminatingGateEnabled)() - endpoint := podToEndpoint(testCase.pod, testCase.node, testCase.svc, discovery.AddressTypeIPv4) if !reflect.DeepEqual(testCase.expectedEndpoint, endpoint) { t.Errorf("Expected endpoint: %+v, got: %+v", testCase.expectedEndpoint, endpoint) diff --git a/pkg/controller/util/endpoint/controller_utils.go b/pkg/controller/util/endpoint/controller_utils.go index addaccc9d68..24410bf8fa0 100644 --- a/pkg/controller/util/endpoint/controller_utils.go +++ b/pkg/controller/util/endpoint/controller_utils.go @@ -306,16 +306,11 @@ func EndpointsEqualBeyondHash(ep1, ep2 *discovery.Endpoint) bool { return false } - // Serving and Terminating will only be set when the EndpointSliceTerminatingCondition feature is on. - // Ignore their difference if the expected or actual value is nil, which means the feature enablement is changed. - // Otherwise all EndpointSlices in the system would be updated on the first controller-manager restart even without - // actual changes, leading to delay in processing legitimate updates. - // Its value will be set to the expected one when there is an actual change triggering update of this EndpointSlice. - if ep1.Conditions.Serving != nil && ep2.Conditions.Serving != nil && *ep1.Conditions.Serving != *ep2.Conditions.Serving { + if boolPtrChanged(ep1.Conditions.Serving, ep2.Conditions.Serving) { return false } - if ep1.Conditions.Terminating != nil && ep2.Conditions.Terminating != nil && *ep1.Conditions.Terminating != *ep2.Conditions.Terminating { + if boolPtrChanged(ep1.Conditions.Terminating, ep2.Conditions.Terminating) { return false } diff --git a/pkg/controller/util/endpoint/controller_utils_test.go b/pkg/controller/util/endpoint/controller_utils_test.go index e9656b0a8dd..c06adb20c93 100644 --- a/pkg/controller/util/endpoint/controller_utils_test.go +++ b/pkg/controller/util/endpoint/controller_utils_test.go @@ -776,7 +776,7 @@ func TestEndpointsEqualBeyondHash(t *testing.T) { Zone: utilpointer.StringPtr("zone-1"), NodeName: utilpointer.StringPtr("node-1"), }, - expected: true, + expected: false, }, { name: "Serving condition changed from false to true", diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 18da94ce825..fac1b67e5ed 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -269,6 +269,7 @@ const ( // kep: https://kep.k8s.io/1672 // alpha: v1.20 // beta: v1.22 + // GA: v1.26 // // Enable Terminating condition in Endpoint Slices. EndpointSliceTerminatingCondition featuregate.Feature = "EndpointSliceTerminatingCondition" @@ -899,7 +900,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS DownwardAPIHugePages: {Default: true, PreRelease: featuregate.Beta}, // on by default in 1.22 - EndpointSliceTerminatingCondition: {Default: true, PreRelease: featuregate.Beta}, + EndpointSliceTerminatingCondition: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in v1.28 EphemeralContainers: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27 diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 0737653b391..c50e2dd7eb0 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -27012,14 +27012,14 @@ func schema_k8sio_api_discovery_v1_EndpointConditions(ref common.ReferenceCallba }, "serving": { SchemaProps: spec.SchemaProps{ - Description: "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + Description: "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition.", Type: []string{"boolean"}, Format: "", }, }, "terminating": { SchemaProps: spec.SchemaProps{ - Description: "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + Description: "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating.", Type: []string{"boolean"}, Format: "", }, @@ -27367,14 +27367,14 @@ func schema_k8sio_api_discovery_v1beta1_EndpointConditions(ref common.ReferenceC }, "serving": { SchemaProps: spec.SchemaProps{ - Description: "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + Description: "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition.", Type: []string{"boolean"}, Format: "", }, }, "terminating": { SchemaProps: spec.SchemaProps{ - Description: "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + Description: "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating.", Type: []string{"boolean"}, Format: "", }, diff --git a/pkg/registry/discovery/endpointslice/strategy.go b/pkg/registry/discovery/endpointslice/strategy.go index 1473563ce10..6bb8359f1e4 100644 --- a/pkg/registry/discovery/endpointslice/strategy.go +++ b/pkg/registry/discovery/endpointslice/strategy.go @@ -123,15 +123,10 @@ func (endpointSliceStrategy) AllowUnconditionalUpdate() bool { // dropDisabledConditionsOnCreate will drop any fields that are disabled. func dropDisabledFieldsOnCreate(endpointSlice *discovery.EndpointSlice) { - dropTerminating := !utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceTerminatingCondition) dropHints := !utilfeature.DefaultFeatureGate.Enabled(features.TopologyAwareHints) - if dropHints || dropTerminating { + if dropHints { for i := range endpointSlice.Endpoints { - if dropTerminating { - endpointSlice.Endpoints[i].Conditions.Serving = nil - endpointSlice.Endpoints[i].Conditions.Terminating = nil - } if dropHints { endpointSlice.Endpoints[i].Hints = nil } @@ -142,16 +137,6 @@ func dropDisabledFieldsOnCreate(endpointSlice *discovery.EndpointSlice) { // dropDisabledFieldsOnUpdate will drop any disable fields that have not already // been set on the EndpointSlice. func dropDisabledFieldsOnUpdate(oldEPS, newEPS *discovery.EndpointSlice) { - dropTerminating := !utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceTerminatingCondition) - if dropTerminating { - for _, ep := range oldEPS.Endpoints { - if ep.Conditions.Serving != nil || ep.Conditions.Terminating != nil { - dropTerminating = false - break - } - } - } - dropHints := !utilfeature.DefaultFeatureGate.Enabled(features.TopologyAwareHints) if dropHints { for _, ep := range oldEPS.Endpoints { @@ -162,12 +147,8 @@ func dropDisabledFieldsOnUpdate(oldEPS, newEPS *discovery.EndpointSlice) { } } - if dropHints || dropTerminating { + if dropHints { for i := range newEPS.Endpoints { - if dropTerminating { - newEPS.Endpoints[i].Conditions.Serving = nil - newEPS.Endpoints[i].Conditions.Terminating = nil - } if dropHints { newEPS.Endpoints[i].Hints = nil } diff --git a/pkg/registry/discovery/endpointslice/strategy_test.go b/pkg/registry/discovery/endpointslice/strategy_test.go index 8dd6a6edb11..6204fe5af62 100644 --- a/pkg/registry/discovery/endpointslice/strategy_test.go +++ b/pkg/registry/discovery/endpointslice/strategy_test.go @@ -34,108 +34,11 @@ import ( func Test_dropDisabledFieldsOnCreate(t *testing.T) { testcases := []struct { - name string - terminatingGateEnabled bool - hintsGateEnabled bool - eps *discovery.EndpointSlice - expectedEPS *discovery.EndpointSlice + name string + hintsGateEnabled bool + eps *discovery.EndpointSlice + expectedEPS *discovery.EndpointSlice }{ - { - name: "terminating gate enabled, field should be allowed", - terminatingGateEnabled: true, - eps: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - expectedEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - }, - { - name: "terminating gate disabled, field should be set to nil", - terminatingGateEnabled: false, - eps: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - expectedEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - }, { name: "node name gate enabled, field should be allowed", eps: &discovery.EndpointSlice{ @@ -163,7 +66,6 @@ func Test_dropDisabledFieldsOnCreate(t *testing.T) { for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testcase.terminatingGateEnabled)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TopologyAwareHints, testcase.hintsGateEnabled)() dropDisabledFieldsOnCreate(testcase.eps) @@ -178,290 +80,12 @@ func Test_dropDisabledFieldsOnCreate(t *testing.T) { func Test_dropDisabledFieldsOnUpdate(t *testing.T) { testcases := []struct { - name string - terminatingGateEnabled bool - hintsGateEnabled bool - oldEPS *discovery.EndpointSlice - newEPS *discovery.EndpointSlice - expectedEPS *discovery.EndpointSlice + name string + hintsGateEnabled bool + oldEPS *discovery.EndpointSlice + newEPS *discovery.EndpointSlice + expectedEPS *discovery.EndpointSlice }{ - { - name: "terminating gate enabled, field should be allowed", - terminatingGateEnabled: true, - oldEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - newEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - expectedEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - }, - { - name: "terminating gate disabled, and not set on existing EPS", - terminatingGateEnabled: false, - oldEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - newEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - expectedEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - }, - { - name: "terminating gate disabled, and set on existing EPS", - terminatingGateEnabled: false, - oldEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - newEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - expectedEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: nil, - Terminating: nil, - }, - }, - }, - }, - }, - { - name: "terminating gate disabled, and set on existing EPS with new values", - terminatingGateEnabled: false, - oldEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(false), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Terminating: nil, - }, - }, - }, - }, - newEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(false), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Terminating: utilpointer.BoolPtr(false), - }, - }, - }, - }, - expectedEPS: &discovery.EndpointSlice{ - Endpoints: []discovery.Endpoint{ - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(true), - Terminating: utilpointer.BoolPtr(true), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Serving: utilpointer.BoolPtr(false), - Terminating: utilpointer.BoolPtr(false), - }, - }, - { - Conditions: discovery.EndpointConditions{ - Terminating: utilpointer.BoolPtr(false), - }, - }, - }, - }, - }, { name: "node name gate enabled, set on new EPS", oldEPS: &discovery.EndpointSlice{ @@ -658,7 +282,6 @@ func Test_dropDisabledFieldsOnUpdate(t *testing.T) { for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testcase.terminatingGateEnabled)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TopologyAwareHints, testcase.hintsGateEnabled)() dropDisabledFieldsOnUpdate(testcase.oldEPS, testcase.newEPS) diff --git a/staging/src/k8s.io/api/discovery/v1/generated.proto b/staging/src/k8s.io/api/discovery/v1/generated.proto index 7ef2a871ebe..9cbe46394a3 100644 --- a/staging/src/k8s.io/api/discovery/v1/generated.proto +++ b/staging/src/k8s.io/api/discovery/v1/generated.proto @@ -93,15 +93,13 @@ message EndpointConditions { // serving is identical to ready except that it is set regardless of the // terminating state of endpoints. This condition should be set to true for // a ready endpoint that is terminating. If nil, consumers should defer to - // the ready condition. This field can be enabled with the - // EndpointSliceTerminatingCondition feature gate. + // the ready condition. // +optional optional bool serving = 2; // terminating indicates that this endpoint is terminating. A nil value // indicates an unknown state. Consumers should interpret this unknown state - // to mean that the endpoint is not terminating. This field can be enabled - // with the EndpointSliceTerminatingCondition feature gate. + // to mean that the endpoint is not terminating. // +optional optional bool terminating = 3; } diff --git a/staging/src/k8s.io/api/discovery/v1/types.go b/staging/src/k8s.io/api/discovery/v1/types.go index 0757a6b8423..2df80c3d5c2 100644 --- a/staging/src/k8s.io/api/discovery/v1/types.go +++ b/staging/src/k8s.io/api/discovery/v1/types.go @@ -126,15 +126,13 @@ type EndpointConditions struct { // serving is identical to ready except that it is set regardless of the // terminating state of endpoints. This condition should be set to true for // a ready endpoint that is terminating. If nil, consumers should defer to - // the ready condition. This field can be enabled with the - // EndpointSliceTerminatingCondition feature gate. + // the ready condition. // +optional Serving *bool `json:"serving,omitempty" protobuf:"bytes,2,name=serving"` // terminating indicates that this endpoint is terminating. A nil value // indicates an unknown state. Consumers should interpret this unknown state - // to mean that the endpoint is not terminating. This field can be enabled - // with the EndpointSliceTerminatingCondition feature gate. + // to mean that the endpoint is not terminating. // +optional Terminating *bool `json:"terminating,omitempty" protobuf:"bytes,3,name=terminating"` } diff --git a/staging/src/k8s.io/api/discovery/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/discovery/v1/types_swagger_doc_generated.go index c83bb014ce6..746408b6685 100644 --- a/staging/src/k8s.io/api/discovery/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/discovery/v1/types_swagger_doc_generated.go @@ -46,8 +46,8 @@ func (Endpoint) SwaggerDoc() map[string]string { var map_EndpointConditions = map[string]string{ "": "EndpointConditions represents the current condition of an endpoint.", "ready": "ready indicates that this endpoint is prepared to receive traffic, according to whatever system is managing the endpoint. A nil value indicates an unknown state. In most cases consumers should interpret this unknown state as ready. For compatibility reasons, ready should never be \"true\" for terminating endpoints.", - "serving": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", - "terminating": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + "serving": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition.", + "terminating": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating.", } func (EndpointConditions) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/discovery/v1beta1/generated.proto b/staging/src/k8s.io/api/discovery/v1beta1/generated.proto index 6f76bb2c626..2979e64a717 100644 --- a/staging/src/k8s.io/api/discovery/v1beta1/generated.proto +++ b/staging/src/k8s.io/api/discovery/v1beta1/generated.proto @@ -97,15 +97,13 @@ message EndpointConditions { // serving is identical to ready except that it is set regardless of the // terminating state of endpoints. This condition should be set to true for // a ready endpoint that is terminating. If nil, consumers should defer to - // the ready condition. This field can be enabled with the - // EndpointSliceTerminatingCondition feature gate. + // the ready condition. // +optional optional bool serving = 2; // terminating indicates that this endpoint is terminating. A nil value // indicates an unknown state. Consumers should interpret this unknown state - // to mean that the endpoint is not terminating. This field can be enabled - // with the EndpointSliceTerminatingCondition feature gate. + // to mean that the endpoint is not terminating. // +optional optional bool terminating = 3; } diff --git a/staging/src/k8s.io/api/discovery/v1beta1/types.go b/staging/src/k8s.io/api/discovery/v1beta1/types.go index 3bc780fadcc..7a02bead595 100644 --- a/staging/src/k8s.io/api/discovery/v1beta1/types.go +++ b/staging/src/k8s.io/api/discovery/v1beta1/types.go @@ -132,15 +132,13 @@ type EndpointConditions struct { // serving is identical to ready except that it is set regardless of the // terminating state of endpoints. This condition should be set to true for // a ready endpoint that is terminating. If nil, consumers should defer to - // the ready condition. This field can be enabled with the - // EndpointSliceTerminatingCondition feature gate. + // the ready condition. // +optional Serving *bool `json:"serving,omitempty" protobuf:"bytes,2,name=serving"` // terminating indicates that this endpoint is terminating. A nil value // indicates an unknown state. Consumers should interpret this unknown state - // to mean that the endpoint is not terminating. This field can be enabled - // with the EndpointSliceTerminatingCondition feature gate. + // to mean that the endpoint is not terminating. // +optional Terminating *bool `json:"terminating,omitempty" protobuf:"bytes,3,name=terminating"` } diff --git a/staging/src/k8s.io/api/discovery/v1beta1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/discovery/v1beta1/types_swagger_doc_generated.go index 122da0620c7..e1c974b3978 100644 --- a/staging/src/k8s.io/api/discovery/v1beta1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/discovery/v1beta1/types_swagger_doc_generated.go @@ -45,8 +45,8 @@ func (Endpoint) SwaggerDoc() map[string]string { var map_EndpointConditions = map[string]string{ "": "EndpointConditions represents the current condition of an endpoint.", "ready": "ready indicates that this endpoint is prepared to receive traffic, according to whatever system is managing the endpoint. A nil value indicates an unknown state. In most cases consumers should interpret this unknown state as ready. For compatibility reasons, ready should never be \"true\" for terminating endpoints.", - "serving": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", - "terminating": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + "serving": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition.", + "terminating": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating.", } func (EndpointConditions) SwaggerDoc() map[string]string { diff --git a/test/integration/endpointslice/endpointsliceterminating_test.go b/test/integration/endpointslice/endpointsliceterminating_test.go index 0eb897f1520..d03af12f541 100644 --- a/test/integration/endpointslice/endpointsliceterminating_test.go +++ b/test/integration/endpointslice/endpointsliceterminating_test.go @@ -27,69 +27,24 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/wait" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" - featuregatetesting "k8s.io/component-base/featuregate/testing" kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" "k8s.io/kubernetes/pkg/controller/endpointslice" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/test/integration/framework" utilpointer "k8s.io/utils/pointer" ) -// TestEndpointSliceTerminating tests that terminating pods are NOT included in EndpointSlice when -// the feature gate EndpointSliceTerminatingCondition is off. If the gate is on, it tests that -// terminating endpoints are included but with the correct conditions set for ready, serving and terminating. +// TestEndpointSliceTerminating tests that terminating endpoints are included with the +// correct conditions set for ready, serving and terminating. func TestEndpointSliceTerminating(t *testing.T) { testcases := []struct { name string podStatus corev1.PodStatus expectedEndpoints []discovery.Endpoint - terminatingGate bool }{ { - name: "ready terminating pods not included, terminating gate off", - podStatus: corev1.PodStatus{ - Phase: corev1.PodRunning, - Conditions: []corev1.PodCondition{ - { - Type: corev1.PodReady, - Status: corev1.ConditionTrue, - }, - }, - PodIP: "10.0.0.1", - PodIPs: []corev1.PodIP{ - { - IP: "10.0.0.1", - }, - }, - }, - expectedEndpoints: []discovery.Endpoint{}, - terminatingGate: false, - }, - { - name: "not ready terminating pods not included, terminating gate off", - podStatus: corev1.PodStatus{ - Phase: corev1.PodRunning, - Conditions: []corev1.PodCondition{ - { - Type: corev1.PodReady, - Status: corev1.ConditionFalse, - }, - }, - PodIP: "10.0.0.1", - PodIPs: []corev1.PodIP{ - { - IP: "10.0.0.1", - }, - }, - }, - expectedEndpoints: []discovery.Endpoint{}, - terminatingGate: false, - }, - { - name: "ready terminating pods included, terminating gate on", + name: "ready terminating pods", podStatus: corev1.PodStatus{ Phase: corev1.PodRunning, Conditions: []corev1.PodCondition{ @@ -115,10 +70,9 @@ func TestEndpointSliceTerminating(t *testing.T) { }, }, }, - terminatingGate: true, }, { - name: "not ready terminating pods included, terminating gate on", + name: "not ready terminating pods", podStatus: corev1.PodStatus{ Phase: corev1.PodRunning, Conditions: []corev1.PodCondition{ @@ -144,14 +98,11 @@ func TestEndpointSliceTerminating(t *testing.T) { }, }, }, - terminatingGate: true, }, } for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testcase.terminatingGate)() - // Disable ServiceAccount admission plugin as we don't have serviceaccount controller running. server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount"}, framework.SharedEtcd()) defer server.TearDownFn()