Add e2eendpointslice.WaitForEndpointSlices, use it in a few places

(This is mostly a helper for the other functions about to be added,
but it's useful by itself in a few places.)
This commit is contained in:
Dan Winship 2025-06-02 20:56:02 -04:00
parent b1b15a57e6
commit 665599417a
3 changed files with 56 additions and 30 deletions

View file

@ -0,0 +1,45 @@
/*
Copyright 2025 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package endpointslice
import (
"context"
"fmt"
"time"
discoveryv1 "k8s.io/api/discovery/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/test/e2e/framework"
)
type EndpointSliceConditionFunc func(ctx context.Context, endpointSlices []discoveryv1.EndpointSlice) (done bool, err error)
// WaitForEndpointSlices is an EndpointSlice-specific wrapper around
// wait.PollUntilContextTimeout that polls conditionFunc with a list of serviceName's
// EndpointSlices.
func WaitForEndpointSlices(ctx context.Context, cs clientset.Interface, namespace, serviceName string, interval, timeout time.Duration, conditionFunc EndpointSliceConditionFunc) error {
return wait.PollUntilContextTimeout(ctx, interval, timeout, true, func(ctx context.Context) (bool, error) {
esList, err := cs.DiscoveryV1().EndpointSlices(namespace).List(ctx, metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", discoveryv1.LabelServiceName, serviceName)})
if err != nil {
framework.Logf("Unexpected error trying to get EndpointSlices for %s/%s: %v", namespace, serviceName, err)
return false, nil
}
return conditionFunc(ctx, esList.Items)
})
}

View file

@ -33,6 +33,7 @@ import (
"k8s.io/kubernetes/test/e2e/framework"
e2edaemonset "k8s.io/kubernetes/test/e2e/framework/daemonset"
e2edeployment "k8s.io/kubernetes/test/e2e/framework/deployment"
e2eendpointslice "k8s.io/kubernetes/test/e2e/framework/endpointslice"
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
"k8s.io/kubernetes/test/e2e/network/common"
@ -170,12 +171,8 @@ var _ = common.SIGDescribe("Networking IPerf2", feature.NetworkingPerformance, f
// Make sure the server is ready to go
framework.Logf("waiting for iperf2 server endpoints")
err = wait.Poll(2*time.Second, largeClusterTimeout, func() (done bool, err error) {
listOptions := metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", discoveryv1.LabelServiceName, serverServiceName)}
esList, err := f.ClientSet.DiscoveryV1().EndpointSlices(f.Namespace.Name).List(ctx, listOptions)
framework.ExpectNoError(err, "Error fetching EndpointSlice for Service %s/%s", f.Namespace.Name, serverServiceName)
if len(esList.Items) == 0 {
err = e2eendpointslice.WaitForEndpointSlices(ctx, f.ClientSet, f.Namespace.Name, serverServiceName, 2*time.Second, largeClusterTimeout, func(ctx context.Context, endpointSlices []discoveryv1.EndpointSlice) (bool, error) {
if len(endpointSlices) == 0 {
framework.Logf("EndpointSlice for Service %s/%s not found", f.Namespace.Name, serverServiceName)
return false, nil
}

View file

@ -26,12 +26,14 @@ import (
"github.com/onsi/ginkgo/v2"
v1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/wait"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/test/e2e/framework"
e2eendpointslice "k8s.io/kubernetes/test/e2e/framework/endpointslice"
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
e2eoutput "k8s.io/kubernetes/test/e2e/framework/pod/output"
e2eservice "k8s.io/kubernetes/test/e2e/framework/service"
@ -162,14 +164,8 @@ var _ = common.SIGDescribe("Connectivity Pod Lifecycle", func() {
}
// Expect EndpointSlice resource to have the blue pod ready to serve traffic
if err := wait.PollUntilContextTimeout(ctx, 2*time.Second, wait.ForeverTestTimeout, true, func(context.Context) (bool, error) {
endpointSliceList, err := cs.DiscoveryV1().EndpointSlices(blueGreenJig.Namespace).List(ctx, metav1.ListOptions{
LabelSelector: "kubernetes.io/service-name=" + blueGreenJig.Name,
})
if err != nil {
return false, err
}
for _, slice := range endpointSliceList.Items {
if err := e2eendpointslice.WaitForEndpointSlices(ctx, cs, blueGreenJig.Namespace, blueGreenJig.Name, 2*time.Second, wait.ForeverTestTimeout, func(ctx context.Context, endpointSlices []discoveryv1.EndpointSlice) (bool, error) {
for _, slice := range endpointSlices {
for _, ep := range slice.Endpoints {
if ep.TargetRef != nil &&
ep.TargetRef.Name == bluePod.Name &&
@ -220,14 +216,8 @@ var _ = common.SIGDescribe("Connectivity Pod Lifecycle", func() {
}
// Expect EndpointSlice resource to have the green pod ready to serve traffic
if err := wait.PollUntilContextTimeout(ctx, 2*time.Second, wait.ForeverTestTimeout, true, func(context.Context) (bool, error) {
endpointSliceList, err := cs.DiscoveryV1().EndpointSlices(blueGreenJig.Namespace).List(ctx, metav1.ListOptions{
LabelSelector: "kubernetes.io/service-name=" + blueGreenJig.Name,
})
if err != nil {
return false, err
}
for _, slice := range endpointSliceList.Items {
if err := e2eendpointslice.WaitForEndpointSlices(ctx, cs, blueGreenJig.Namespace, blueGreenJig.Name, 2*time.Second, wait.ForeverTestTimeout, func(ctx context.Context, endpointSlices []discoveryv1.EndpointSlice) (bool, error) {
for _, slice := range endpointSlices {
for _, ep := range slice.Endpoints {
if ep.TargetRef != nil &&
ep.TargetRef.Name == greenPod.Name &&
@ -249,14 +239,8 @@ var _ = common.SIGDescribe("Connectivity Pod Lifecycle", func() {
}
// Expect EndpointSlice resource to have the blue pod NOT ready to serve traffic
if err := wait.PollUntilContextTimeout(ctx, 2*time.Second, wait.ForeverTestTimeout, true, func(context.Context) (bool, error) {
endpointSliceList, err := cs.DiscoveryV1().EndpointSlices(blueGreenJig.Namespace).List(ctx, metav1.ListOptions{
LabelSelector: "kubernetes.io/service-name=" + blueGreenJig.Name,
})
if err != nil {
return false, err
}
for _, slice := range endpointSliceList.Items {
if err := e2eendpointslice.WaitForEndpointSlices(ctx, cs, blueGreenJig.Namespace, blueGreenJig.Name, 2*time.Second, wait.ForeverTestTimeout, func(ctx context.Context, endpointSlices []discoveryv1.EndpointSlice) (bool, error) {
for _, slice := range endpointSlices {
for _, ep := range slice.Endpoints {
if ep.TargetRef != nil &&
ep.TargetRef.Name == bluePod.Name &&