mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 01:40:13 +00:00
Merge pull request #113298 from pohly/e2e-wait-for-pods-with-gomega
e2e: wait for pods with gomega
This commit is contained in:
commit
85aa0057c6
@ -73,7 +73,7 @@ func restartAPIServer(ctx context.Context, node *v1.Node) error {
|
||||
result, err := e2essh.SSH(ctx, cmd, net.JoinHostPort(controlPlaneAddress, e2essh.SSHPort), framework.TestContext.Provider)
|
||||
if err != nil || result.Code != 0 {
|
||||
e2essh.LogResult(result)
|
||||
return fmt.Errorf("couldn't restart kube-apiserver: %v", err)
|
||||
return fmt.Errorf("couldn't restart kube-apiserver: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -561,7 +561,7 @@ func setupCRDAndVerifySchemaWithOptions(f *framework.Framework, schema, expect [
|
||||
})
|
||||
crd, err := crd.CreateMultiVersionTestCRD(f, group, options...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create CRD: %v", err)
|
||||
return nil, fmt.Errorf("failed to create CRD: %w", err)
|
||||
}
|
||||
|
||||
for _, v := range crd.Crd.Spec.Versions {
|
||||
@ -623,7 +623,7 @@ func waitForDefinition(c k8sclientset.Interface, name string, schema []byte) err
|
||||
return true, ""
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to wait for definition %q to be served with the right OpenAPI schema: %v", name, err)
|
||||
return fmt.Errorf("failed to wait for definition %q to be served with the right OpenAPI schema: %w", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -637,7 +637,7 @@ func waitForDefinitionCleanup(c k8sclientset.Interface, name string) error {
|
||||
return true, ""
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to wait for definition %q not to be served anymore: %v", name, err)
|
||||
return fmt.Errorf("failed to wait for definition %q not to be served anymore: %w", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -718,7 +718,7 @@ func dropDefaults(s *spec.Schema) {
|
||||
func verifyKubectlExplain(ns, name, pattern string) error {
|
||||
result, err := e2ekubectl.RunKubectl(ns, "explain", name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to explain %s: %v", name, err)
|
||||
return fmt.Errorf("failed to explain %s: %w", name, err)
|
||||
}
|
||||
r := regexp.MustCompile(pattern)
|
||||
if !r.Match([]byte(result)) {
|
||||
|
@ -181,7 +181,7 @@ func verifyRemainingObjects(ctx context.Context, f *framework.Framework, objects
|
||||
case "Pods":
|
||||
pods, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list pods: %v", err)
|
||||
return false, fmt.Errorf("failed to list pods: %w", err)
|
||||
}
|
||||
if len(pods.Items) != num {
|
||||
ret = false
|
||||
@ -190,7 +190,7 @@ func verifyRemainingObjects(ctx context.Context, f *framework.Framework, objects
|
||||
case "Deployments":
|
||||
deployments, err := f.ClientSet.AppsV1().Deployments(f.Namespace.Name).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list deployments: %v", err)
|
||||
return false, fmt.Errorf("failed to list deployments: %w", err)
|
||||
}
|
||||
if len(deployments.Items) != num {
|
||||
ret = false
|
||||
@ -199,7 +199,7 @@ func verifyRemainingObjects(ctx context.Context, f *framework.Framework, objects
|
||||
case "ReplicaSets":
|
||||
rs, err := f.ClientSet.AppsV1().ReplicaSets(f.Namespace.Name).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list rs: %v", err)
|
||||
return false, fmt.Errorf("failed to list rs: %w", err)
|
||||
}
|
||||
if len(rs.Items) != num {
|
||||
ret = false
|
||||
@ -208,7 +208,7 @@ func verifyRemainingObjects(ctx context.Context, f *framework.Framework, objects
|
||||
case "ReplicationControllers":
|
||||
rcs, err := f.ClientSet.CoreV1().ReplicationControllers(f.Namespace.Name).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list replication controllers: %v", err)
|
||||
return false, fmt.Errorf("failed to list replication controllers: %w", err)
|
||||
}
|
||||
if len(rcs.Items) != num {
|
||||
ret = false
|
||||
@ -217,7 +217,7 @@ func verifyRemainingObjects(ctx context.Context, f *framework.Framework, objects
|
||||
case "CronJobs":
|
||||
cronJobs, err := f.ClientSet.BatchV1().CronJobs(f.Namespace.Name).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list cronjobs: %v", err)
|
||||
return false, fmt.Errorf("failed to list cronjobs: %w", err)
|
||||
}
|
||||
if len(cronJobs.Items) != num {
|
||||
ret = false
|
||||
@ -226,7 +226,7 @@ func verifyRemainingObjects(ctx context.Context, f *framework.Framework, objects
|
||||
case "Jobs":
|
||||
jobs, err := f.ClientSet.BatchV1().Jobs(f.Namespace.Name).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list jobs: %v", err)
|
||||
return false, fmt.Errorf("failed to list jobs: %w", err)
|
||||
}
|
||||
if len(jobs.Items) != num {
|
||||
ret = false
|
||||
@ -325,7 +325,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
if err := wait.Poll(5*time.Second, 30*time.Second, func() (bool, error) {
|
||||
pods, err := podClient.List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list pods: %v", err)
|
||||
return false, fmt.Errorf("failed to list pods: %w", err)
|
||||
}
|
||||
// We intentionally don't wait the number of pods to reach
|
||||
// rc.Spec.Replicas. We want to see if the garbage collector and the
|
||||
@ -383,7 +383,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
if err := wait.PollWithContext(ctx, 5*time.Second, 30*time.Second, func(ctx context.Context) (bool, error) {
|
||||
rc, err := rcClient.Get(ctx, rc.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get rc: %v", err)
|
||||
return false, fmt.Errorf("failed to get rc: %w", err)
|
||||
}
|
||||
if rc.Status.Replicas == *rc.Spec.Replicas {
|
||||
return true, nil
|
||||
@ -410,7 +410,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
if err := wait.PollWithContext(ctx, 5*time.Second, 120*time.Second+gcInformerResyncRetryTimeout, func(ctx context.Context) (bool, error) {
|
||||
rcs, err := rcClient.List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list rcs: %v", err)
|
||||
return false, fmt.Errorf("failed to list rcs: %w", err)
|
||||
}
|
||||
if len(rcs.Items) != 0 {
|
||||
return false, nil
|
||||
@ -452,7 +452,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
if err := wait.PollWithContext(ctx, 5*time.Second, 30*time.Second, func(ctx context.Context) (bool, error) {
|
||||
rc, err := rcClient.Get(ctx, rc.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get rc: %v", err)
|
||||
return false, fmt.Errorf("failed to get rc: %w", err)
|
||||
}
|
||||
if rc.Status.Replicas == *rc.Spec.Replicas {
|
||||
return true, nil
|
||||
@ -505,7 +505,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
err = wait.PollImmediateWithContext(ctx, 500*time.Millisecond, 1*time.Minute, func(ctx context.Context) (bool, error) {
|
||||
rsList, err := rsClient.List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list rs: %v", err)
|
||||
return false, fmt.Errorf("failed to list rs: %w", err)
|
||||
}
|
||||
return len(rsList.Items) > 0, nil
|
||||
|
||||
@ -530,7 +530,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
errList = append(errList, err)
|
||||
remainingRSs, err := rsClient.List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
errList = append(errList, fmt.Errorf("failed to list RSs post mortem: %v", err))
|
||||
errList = append(errList, fmt.Errorf("failed to list RSs post mortem: %w", err))
|
||||
} else {
|
||||
errList = append(errList, fmt.Errorf("remaining rs are: %#v", remainingRSs))
|
||||
}
|
||||
@ -565,7 +565,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
err = wait.PollImmediateWithContext(ctx, 500*time.Millisecond, 1*time.Minute, func(ctx context.Context) (bool, error) {
|
||||
rsList, err := rsClient.List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list rs: %v", err)
|
||||
return false, fmt.Errorf("failed to list rs: %w", err)
|
||||
}
|
||||
if len(rsList.Items) > 0 {
|
||||
replicaset = rsList.Items[0]
|
||||
@ -599,7 +599,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
err = wait.PollImmediateWithContext(ctx, 500*time.Millisecond, 1*time.Minute+gcInformerResyncRetryTimeout, func(ctx context.Context) (bool, error) {
|
||||
dList, err := deployClient.List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list deployments: %v", err)
|
||||
return false, fmt.Errorf("failed to list deployments: %w", err)
|
||||
}
|
||||
return len(dList.Items) == 0, nil
|
||||
})
|
||||
@ -616,13 +616,13 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
errList := make([]error, 0)
|
||||
remainingRSs, err := rsClient.List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
errList = append(errList, fmt.Errorf("failed to list RSs post mortem: %v", err))
|
||||
errList = append(errList, fmt.Errorf("failed to list RSs post mortem: %w", err))
|
||||
} else {
|
||||
errList = append(errList, fmt.Errorf("remaining rs post mortem: %#v", remainingRSs))
|
||||
}
|
||||
remainingDSs, err := deployClient.List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
errList = append(errList, fmt.Errorf("failed to list Deployments post mortem: %v", err))
|
||||
errList = append(errList, fmt.Errorf("failed to list Deployments post mortem: %w", err))
|
||||
} else {
|
||||
errList = append(errList, fmt.Errorf("remaining deployment's post mortem: %#v", remainingDSs))
|
||||
}
|
||||
@ -663,7 +663,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
if err := wait.PollWithContext(ctx, 5*time.Second, 30*time.Second, func(ctx context.Context) (bool, error) {
|
||||
rc, err := rcClient.Get(ctx, rc.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get rc: %v", err)
|
||||
return false, fmt.Errorf("failed to get rc: %w", err)
|
||||
}
|
||||
if rc.Status.Replicas == *rc.Spec.Replicas {
|
||||
return true, nil
|
||||
@ -758,7 +758,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
if err := wait.PollWithContext(ctx, 5*time.Second, 30*time.Second, func(ctx context.Context) (bool, error) {
|
||||
rc1, err := rcClient.Get(ctx, rc1.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get rc: %v", err)
|
||||
return false, fmt.Errorf("failed to get rc: %w", err)
|
||||
}
|
||||
if rc1.Status.Replicas == *rc1.Spec.Replicas {
|
||||
return true, nil
|
||||
@ -889,7 +889,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
if err := wait.PollWithContext(ctx, 5*time.Second, 90*time.Second+gcInformerResyncRetryTimeout, func(ctx context.Context) (bool, error) {
|
||||
pods, err2 = podClient.List(ctx, metav1.ListOptions{})
|
||||
if err2 != nil {
|
||||
return false, fmt.Errorf("failed to list pods: %v", err)
|
||||
return false, fmt.Errorf("failed to list pods: %w", err)
|
||||
}
|
||||
if len(pods.Items) == 0 {
|
||||
return true, nil
|
||||
@ -1125,7 +1125,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
return false, fmt.Errorf("failed to get owner: %v", err)
|
||||
return false, fmt.Errorf("failed to get owner: %w", err)
|
||||
}
|
||||
return true, nil
|
||||
}); err != nil {
|
||||
@ -1153,7 +1153,7 @@ var _ = SIGDescribe("Garbage collector", func() {
|
||||
err = wait.PollImmediateWithContext(ctx, 500*time.Millisecond, 2*time.Minute, func(ctx context.Context) (bool, error) {
|
||||
jobs, err := f.ClientSet.BatchV1().Jobs(f.Namespace.Name).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list jobs: %v", err)
|
||||
return false, fmt.Errorf("failed to list jobs: %w", err)
|
||||
}
|
||||
return len(jobs.Items) > 0, nil
|
||||
})
|
||||
|
@ -1250,7 +1250,7 @@ func waitFailedDaemonPodDeleted(c clientset.Interface, pod *v1.Pod) func(ctx con
|
||||
if apierrors.IsNotFound(err) {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("failed to get failed daemon pod %q: %v", pod.Name, err)
|
||||
return false, fmt.Errorf("failed to get failed daemon pod %q: %w", pod.Name, err)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ import (
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilrand "k8s.io/apimachinery/pkg/util/rand"
|
||||
@ -513,9 +512,9 @@ func TestReplicationControllerServeImageOrFail(ctx context.Context, f *framework
|
||||
if err != nil {
|
||||
updatePod, getErr := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(ctx, pod.Name, metav1.GetOptions{})
|
||||
if getErr == nil {
|
||||
err = fmt.Errorf("pod %q never run (phase: %s, conditions: %+v): %v", updatePod.Name, updatePod.Status.Phase, updatePod.Status.Conditions, err)
|
||||
err = fmt.Errorf("pod %q never run (phase: %s, conditions: %+v): %w", updatePod.Name, updatePod.Status.Phase, updatePod.Status.Conditions, err)
|
||||
} else {
|
||||
err = fmt.Errorf("pod %q never run: %v", pod.Name, err)
|
||||
err = fmt.Errorf("pod %q never run: %w", pod.Name, err)
|
||||
}
|
||||
}
|
||||
framework.ExpectNoError(err)
|
||||
@ -528,13 +527,7 @@ func TestReplicationControllerServeImageOrFail(ctx context.Context, f *framework
|
||||
|
||||
// Verify that something is listening.
|
||||
framework.Logf("Trying to dial the pod")
|
||||
retryTimeout := 2 * time.Minute
|
||||
retryInterval := 5 * time.Second
|
||||
label := labels.SelectorFromSet(labels.Set(map[string]string{"name": name}))
|
||||
err = wait.PollWithContext(ctx, retryInterval, retryTimeout, e2epod.NewProxyResponseChecker(f.ClientSet, f.Namespace.Name, label, name, true, pods).CheckAllResponses)
|
||||
if err != nil {
|
||||
framework.Failf("Did not get expected responses within the timeout period of %.2f seconds.", retryTimeout.Seconds())
|
||||
}
|
||||
framework.ExpectNoError(e2epod.WaitForPodsResponding(ctx, f.ClientSet, f.Namespace.Name, name, true, 2*time.Minute, pods))
|
||||
}
|
||||
|
||||
// 1. Create a quota restricting pods in the current namespace to 2.
|
||||
|
@ -210,9 +210,9 @@ func testReplicaSetServeImageOrFail(ctx context.Context, f *framework.Framework,
|
||||
if err != nil {
|
||||
updatePod, getErr := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(ctx, pod.Name, metav1.GetOptions{})
|
||||
if getErr == nil {
|
||||
err = fmt.Errorf("pod %q never run (phase: %s, conditions: %+v): %v", updatePod.Name, updatePod.Status.Phase, updatePod.Status.Conditions, err)
|
||||
err = fmt.Errorf("pod %q never run (phase: %s, conditions: %+v): %w", updatePod.Name, updatePod.Status.Phase, updatePod.Status.Conditions, err)
|
||||
} else {
|
||||
err = fmt.Errorf("pod %q never run: %v", pod.Name, err)
|
||||
err = fmt.Errorf("pod %q never run: %w", pod.Name, err)
|
||||
}
|
||||
}
|
||||
framework.ExpectNoError(err)
|
||||
@ -225,13 +225,7 @@ func testReplicaSetServeImageOrFail(ctx context.Context, f *framework.Framework,
|
||||
|
||||
// Verify that something is listening.
|
||||
framework.Logf("Trying to dial the pod")
|
||||
retryTimeout := 2 * time.Minute
|
||||
retryInterval := 5 * time.Second
|
||||
label := labels.SelectorFromSet(labels.Set(map[string]string{"name": name}))
|
||||
err = wait.PollWithContext(ctx, retryInterval, retryTimeout, e2epod.NewProxyResponseChecker(f.ClientSet, f.Namespace.Name, label, name, true, pods).CheckAllResponses)
|
||||
if err != nil {
|
||||
framework.Failf("Did not get expected responses within the timeout period of %.2f seconds.", retryTimeout.Seconds())
|
||||
}
|
||||
framework.ExpectNoError(e2epod.WaitForPodsResponding(ctx, f.ClientSet, f.Namespace.Name, name, true, 2*time.Minute, pods))
|
||||
}
|
||||
|
||||
// 1. Create a quota restricting pods in the current namespace to 2.
|
||||
|
@ -493,9 +493,7 @@ var _ = SIGDescribe("ServiceAccounts", func() {
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
framework.Logf("created pod")
|
||||
if !e2epod.CheckPodsRunningReady(ctx, f.ClientSet, f.Namespace.Name, []string{pod.Name}, time.Minute) {
|
||||
framework.Failf("pod %q in ns %q never became ready", pod.Name, f.Namespace.Name)
|
||||
}
|
||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(ctx, f.ClientSet, pod.Name, f.Namespace.Name, time.Minute))
|
||||
|
||||
framework.Logf("pod is ready")
|
||||
|
||||
@ -509,7 +507,7 @@ var _ = SIGDescribe("ServiceAccounts", func() {
|
||||
}
|
||||
tokenCount, err := ParseInClusterClientLogs(logs)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("inclusterclient reported an error: %v", err)
|
||||
return false, fmt.Errorf("inclusterclient reported an error: %w", err)
|
||||
}
|
||||
if tokenCount < 2 {
|
||||
framework.Logf("Retrying. Still waiting to see more unique tokens: got=%d, want=2", tokenCount)
|
||||
|
@ -1166,7 +1166,7 @@ func enableAutoscaler(nodePool string, minCount, maxCount int) error {
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("Failed config update result: %s", output)
|
||||
return fmt.Errorf("Failed to enable autoscaling: %v", err)
|
||||
return fmt.Errorf("Failed to enable autoscaling: %w", err)
|
||||
}
|
||||
klog.Infof("Config update result: %s", output)
|
||||
|
||||
@ -1190,7 +1190,7 @@ func disableAutoscaler(nodePool string, minCount, maxCount int) error {
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("Failed config update result: %s", output)
|
||||
return fmt.Errorf("Failed to disable autoscaling: %v", err)
|
||||
return fmt.Errorf("Failed to disable autoscaling: %w", err)
|
||||
}
|
||||
klog.Infof("Config update result: %s", output)
|
||||
|
||||
@ -1384,7 +1384,7 @@ func waitForCaPodsReadyInNamespace(ctx context.Context, f *framework.Framework,
|
||||
for start := time.Now(); time.Now().Before(start.Add(scaleUpTimeout)) && ctx.Err() == nil; time.Sleep(20 * time.Second) {
|
||||
pods, err := c.CoreV1().Pods(f.Namespace.Name).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get pods: %v", err)
|
||||
return fmt.Errorf("failed to get pods: %w", err)
|
||||
}
|
||||
notready = make([]string, 0)
|
||||
for _, pod := range pods.Items {
|
||||
|
@ -355,7 +355,7 @@ func waitForDNSReplicasSatisfied(ctx context.Context, c clientset.Interface, get
|
||||
}
|
||||
|
||||
if err = wait.Poll(2*time.Second, timeout, condition); err != nil {
|
||||
return fmt.Errorf("err waiting for DNS replicas to satisfy %v, got %v: %v", expected, current, err)
|
||||
return fmt.Errorf("err waiting for DNS replicas to satisfy %v, got %v: %w", expected, current, err)
|
||||
}
|
||||
framework.Logf("kube-dns reaches expected replicas: %v", expected)
|
||||
return nil
|
||||
@ -372,7 +372,7 @@ func waitForDNSConfigMapCreated(ctx context.Context, c clientset.Interface, time
|
||||
}
|
||||
|
||||
if err = wait.Poll(time.Second, timeout, condition); err != nil {
|
||||
return nil, fmt.Errorf("err waiting for DNS autoscaling ConfigMap got re-created: %v", err)
|
||||
return nil, fmt.Errorf("err waiting for DNS autoscaling ConfigMap got re-created: %w", err)
|
||||
}
|
||||
return configMap, nil
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ func waitForReplicationController(ctx context.Context, c clientset.Interface, na
|
||||
})
|
||||
if err != nil {
|
||||
stateMsg := map[bool]string{true: "to appear", false: "to disappear"}
|
||||
return fmt.Errorf("error waiting for ReplicationController %s/%s %s: %v", namespace, name, stateMsg[exist], err)
|
||||
return fmt.Errorf("error waiting for ReplicationController %s/%s %s: %w", namespace, name, stateMsg[exist], err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -402,7 +402,7 @@ func waitForServiceWithSelector(ctx context.Context, c clientset.Interface, name
|
||||
})
|
||||
if err != nil {
|
||||
stateMsg := map[bool]string{true: "to appear", false: "to disappear"}
|
||||
return fmt.Errorf("error waiting for service with %s in namespace %s %s: %v", selector.String(), namespace, stateMsg[exist], err)
|
||||
return fmt.Errorf("error waiting for service with %s in namespace %s %s: %w", selector.String(), namespace, stateMsg[exist], err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -426,7 +426,7 @@ func waitForReplicationControllerWithSelector(ctx context.Context, c clientset.I
|
||||
})
|
||||
if err != nil {
|
||||
stateMsg := map[bool]string{true: "to appear", false: "to disappear"}
|
||||
return fmt.Errorf("error waiting for ReplicationControllers with %s in namespace %s %s: %v", selector.String(), namespace, stateMsg[exist], err)
|
||||
return fmt.Errorf("error waiting for ReplicationControllers with %s in namespace %s %s: %w", selector.String(), namespace, stateMsg[exist], err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -437,7 +437,7 @@ func getMasterSSHClient() (*ssh.Client, error) {
|
||||
// Get a signer for the provider.
|
||||
signer, err := e2essh.GetSigner(framework.TestContext.Provider)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting signer for provider %s: '%v'", framework.TestContext.Provider, err)
|
||||
return nil, fmt.Errorf("error getting signer for provider %s: %w", framework.TestContext.Provider, err)
|
||||
}
|
||||
|
||||
sshUser := os.Getenv("KUBE_SSH_USER")
|
||||
@ -453,7 +453,7 @@ func getMasterSSHClient() (*ssh.Client, error) {
|
||||
host := framework.APIAddress() + ":22"
|
||||
client, err := ssh.Dial("tcp", host, config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting SSH client to host %s: '%v'", host, err)
|
||||
return nil, fmt.Errorf("error getting SSH client to host %s: %w", host, err)
|
||||
}
|
||||
return client, err
|
||||
}
|
||||
@ -468,7 +468,7 @@ func sshExec(client *ssh.Client, cmd string) (string, string, int, error) {
|
||||
framework.Logf("Executing '%s' on %v", cmd, client.RemoteAddr())
|
||||
session, err := client.NewSession()
|
||||
if err != nil {
|
||||
return "", "", 0, fmt.Errorf("error creating session to host %s: '%v'", client.RemoteAddr(), err)
|
||||
return "", "", 0, fmt.Errorf("error creating session to host %s: %w", client.RemoteAddr(), err)
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
@ -490,7 +490,7 @@ func sshExec(client *ssh.Client, cmd string) (string, string, int, error) {
|
||||
} else {
|
||||
// Some other kind of error happened (e.g. an IOError); consider the
|
||||
// SSH unsuccessful.
|
||||
err = fmt.Errorf("failed running `%s` on %s: '%v'", cmd, client.RemoteAddr(), err)
|
||||
err = fmt.Errorf("failed running `%s` on %s: %w", cmd, client.RemoteAddr(), err)
|
||||
}
|
||||
}
|
||||
return bout.String(), berr.String(), code, err
|
||||
@ -500,7 +500,7 @@ func writeRemoteFile(sshClient *ssh.Client, data, dir, fileName string, mode os.
|
||||
framework.Logf(fmt.Sprintf("Writing remote file '%s/%s' on %v", dir, fileName, sshClient.RemoteAddr()))
|
||||
session, err := sshClient.NewSession()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating session to host %s: '%v'", sshClient.RemoteAddr(), err)
|
||||
return fmt.Errorf("error creating session to host %s: %w", sshClient.RemoteAddr(), err)
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
|
@ -82,7 +82,7 @@ func realVersion(s string) (string, error) {
|
||||
framework.Logf("Getting real version for %q", s)
|
||||
v, _, err := framework.RunCmd(path.Join(framework.TestContext.RepoRoot, "hack/get-build.sh"), "-v", s)
|
||||
if err != nil {
|
||||
return v, fmt.Errorf("error getting real version for %q: %v", s, err)
|
||||
return v, fmt.Errorf("error getting real version for %q: %w", s, err)
|
||||
}
|
||||
framework.Logf("Version for %q is %q", s, v)
|
||||
return strings.TrimPrefix(strings.TrimSpace(v), "v"), nil
|
||||
|
@ -131,7 +131,7 @@ func checkControlPlaneVersion(ctx context.Context, c clientset.Interface, want s
|
||||
return true, nil
|
||||
})
|
||||
if waitErr != nil {
|
||||
return fmt.Errorf("CheckControlPlane() couldn't get the control plane version: %v", err)
|
||||
return fmt.Errorf("CheckControlPlane() couldn't get the control plane version: %w", err)
|
||||
}
|
||||
// We do prefix trimming and then matching because:
|
||||
// want looks like: 0.19.3-815-g50e67d4
|
||||
|
@ -97,7 +97,7 @@ var _ = SIGDescribe("[Disruptive]NodeLease", func() {
|
||||
// Many e2e tests assume that the cluster is fully healthy before they start. Wait until
|
||||
// the cluster is restored to health.
|
||||
ginkgo.By("waiting for system pods to successfully restart")
|
||||
err := e2epod.WaitForPodsRunningReady(ctx, c, metav1.NamespaceSystem, systemPodsNo, 0, framework.PodReadyBeforeTimeout, map[string]string{})
|
||||
err := e2epod.WaitForPodsRunningReady(ctx, c, metav1.NamespaceSystem, systemPodsNo, 0, framework.PodReadyBeforeTimeout)
|
||||
framework.ExpectNoError(err)
|
||||
})
|
||||
|
||||
|
@ -99,7 +99,7 @@ var _ = SIGDescribe("Nodes [Disruptive]", func() {
|
||||
// Many e2e tests assume that the cluster is fully healthy before they start. Wait until
|
||||
// the cluster is restored to health.
|
||||
ginkgo.By("waiting for system pods to successfully restart")
|
||||
err := e2epod.WaitForPodsRunningReady(ctx, c, metav1.NamespaceSystem, systemPodsNo, 0, framework.PodReadyBeforeTimeout, map[string]string{})
|
||||
err := e2epod.WaitForPodsRunningReady(ctx, c, metav1.NamespaceSystem, systemPodsNo, 0, framework.PodReadyBeforeTimeout)
|
||||
framework.ExpectNoError(err)
|
||||
})
|
||||
})
|
||||
|
@ -608,7 +608,7 @@ done
|
||||
})
|
||||
|
||||
// verify pods are running and ready
|
||||
err := e2epod.WaitForPodsRunningReady(ctx, f.ClientSet, f.Namespace.Name, 1, 0, f.Timeouts.PodStart, map[string]string{})
|
||||
err := e2epod.WaitForPodsRunningReady(ctx, f.ClientSet, f.Namespace.Name, 1, 0, f.Timeouts.PodStart)
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
// Shutdown pod. Readiness should change to false
|
||||
@ -690,7 +690,7 @@ done
|
||||
})
|
||||
|
||||
// verify pods are running and ready
|
||||
err := e2epod.WaitForPodsRunningReady(ctx, f.ClientSet, f.Namespace.Name, 1, 0, f.Timeouts.PodStart, map[string]string{})
|
||||
err := e2epod.WaitForPodsRunningReady(ctx, f.ClientSet, f.Namespace.Name, 1, 0, f.Timeouts.PodStart)
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
// Shutdown pod. Readiness should change to false
|
||||
|
@ -39,15 +39,15 @@ import (
|
||||
func getPatchBytes(oldLease, newLease *coordinationv1.Lease) ([]byte, error) {
|
||||
oldData, err := json.Marshal(oldLease)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to Marshal oldData: %v", err)
|
||||
return nil, fmt.Errorf("failed to Marshal oldData: %w", err)
|
||||
}
|
||||
newData, err := json.Marshal(newLease)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to Marshal newData: %v", err)
|
||||
return nil, fmt.Errorf("failed to Marshal newData: %w", err)
|
||||
}
|
||||
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, coordinationv1.Lease{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to CreateTwoWayMergePatch: %v", err)
|
||||
return nil, fmt.Errorf("failed to CreateTwoWayMergePatch: %w", err)
|
||||
}
|
||||
return patchBytes, nil
|
||||
}
|
||||
|
@ -873,7 +873,7 @@ var _ = SIGDescribe("Pods", func() {
|
||||
|
||||
// wait as required for all 3 pods to be running
|
||||
ginkgo.By("waiting for all 3 pods to be running")
|
||||
err := e2epod.WaitForPodsRunningReady(ctx, f.ClientSet, f.Namespace.Name, 3, 0, f.Timeouts.PodStart, nil)
|
||||
err := e2epod.WaitForPodsRunningReady(ctx, f.ClientSet, f.Namespace.Name, 3, 0, f.Timeouts.PodStart)
|
||||
framework.ExpectNoError(err, "3 pods not found running.")
|
||||
|
||||
// delete Collection of pods with a label in the current namespace
|
||||
|
@ -310,7 +310,7 @@ while true; do sleep 1; done
|
||||
checkContainerStatus := func(ctx context.Context) error {
|
||||
status, err := container.GetStatus(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get container status: %v", err)
|
||||
return fmt.Errorf("failed to get container status: %w", err)
|
||||
}
|
||||
// We need to check container state first. The default pod status is pending, If we check pod phase first,
|
||||
// and the expected pod phase is Pending, the container status may not even show up when we check it.
|
||||
@ -335,7 +335,7 @@ while true; do sleep 1; done
|
||||
// Check pod phase
|
||||
phase, err := container.GetPhase(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get pod phase: %v", err)
|
||||
return fmt.Errorf("failed to get pod phase: %w", err)
|
||||
}
|
||||
if phase != expectedPhase {
|
||||
return fmt.Errorf("expected pod phase: %q, got: %q", expectedPhase, phase)
|
||||
|
@ -195,11 +195,11 @@ func RestartNodes(c clientset.Interface, nodes []v1.Node) error {
|
||||
if err := wait.Poll(30*time.Second, framework.RestartNodeReadyAgainTimeout, func() (bool, error) {
|
||||
newNode, err := c.CoreV1().Nodes().Get(context.TODO(), node.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error getting node info after reboot: %s", err)
|
||||
return false, fmt.Errorf("error getting node info after reboot: %w", err)
|
||||
}
|
||||
return node.Status.NodeInfo.BootID != newNode.Status.NodeInfo.BootID, nil
|
||||
}); err != nil {
|
||||
return fmt.Errorf("error waiting for node %s boot ID to change: %s", node.Name, err)
|
||||
return fmt.Errorf("error waiting for node %s boot ID to change: %w", node.Name, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -110,7 +110,7 @@ var _ = ginkgo.Describe("[sig-node] DRA [Feature:DynamicResourceAllocation]", fu
|
||||
gomega.Consistently(func() error {
|
||||
testPod, err := b.f.ClientSet.CoreV1().Pods(pod.Namespace).Get(context.TODO(), pod.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("expected the test pod %s to exist: %v", pod.Name, err)
|
||||
return fmt.Errorf("expected the test pod %s to exist: %w", pod.Name, err)
|
||||
}
|
||||
if testPod.Status.Phase != v1.PodPending {
|
||||
return fmt.Errorf("pod %s: unexpected status %s, expected status: %s", pod.Name, testPod.Status.Phase, v1.PodPending)
|
||||
|
@ -148,7 +148,7 @@ func (c *ExampleController) GetClaimParameters(ctx context.Context, claim *resou
|
||||
func (c *ExampleController) readParametersFromConfigMap(ctx context.Context, namespace, name string) (map[string]string, error) {
|
||||
configMap, err := c.clientset.CoreV1().ConfigMaps(namespace).Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get config map: %v", err)
|
||||
return nil, fmt.Errorf("get config map: %w", err)
|
||||
}
|
||||
return configMap.Data, nil
|
||||
}
|
||||
@ -221,7 +221,7 @@ func (c *ExampleController) allocate(ctx context.Context, claim *resourcev1alpha
|
||||
toEnvVars("admin", classParameters, p.EnvVars)
|
||||
data, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("encode parameters: %v", err)
|
||||
return nil, fmt.Errorf("encode parameters: %w", err)
|
||||
}
|
||||
allocation.ResourceHandle = string(data)
|
||||
var nodes []string
|
||||
|
@ -97,7 +97,7 @@ func StartPlugin(logger klog.Logger, cdiDir, driverName string, nodeName string,
|
||||
)
|
||||
d, err := kubeletplugin.Start(ex, opts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("start kubelet plugin: %v", err)
|
||||
return nil, fmt.Errorf("start kubelet plugin: %w", err)
|
||||
}
|
||||
ex.d = d
|
||||
|
||||
@ -127,7 +127,7 @@ func (ex *ExamplePlugin) NodePrepareResource(ctx context.Context, req *drapbv1.N
|
||||
// Determine environment variables.
|
||||
var p parameters
|
||||
if err := json.Unmarshal([]byte(req.ResourceHandle), &p); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal resource handle: %v", err)
|
||||
return nil, fmt.Errorf("unmarshal resource handle: %w", err)
|
||||
}
|
||||
|
||||
// Sanity check scheduling.
|
||||
@ -161,7 +161,7 @@ func (ex *ExamplePlugin) NodePrepareResource(ctx context.Context, req *drapbv1.N
|
||||
filePath := ex.getJSONFilePath(req.ClaimUid)
|
||||
buffer, err := json.Marshal(spec)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal spec: %v", err)
|
||||
return nil, fmt.Errorf("marshal spec: %w", err)
|
||||
}
|
||||
if err := ex.fileOps.Create(filePath, buffer); err != nil {
|
||||
return nil, fmt.Errorf("failed to write CDI file %v", err)
|
||||
@ -186,7 +186,7 @@ func (ex *ExamplePlugin) NodeUnprepareResource(ctx context.Context, req *drapbv1
|
||||
|
||||
filePath := ex.getJSONFilePath(req.ClaimUid)
|
||||
if err := ex.fileOps.Remove(filePath); err != nil {
|
||||
return nil, fmt.Errorf("error removing CDI file: %v", err)
|
||||
return nil, fmt.Errorf("error removing CDI file: %w", err)
|
||||
}
|
||||
logger.V(3).Info("CDI file removed", "path", filePath)
|
||||
|
||||
|
@ -115,12 +115,12 @@ func NewCommand() *cobra.Command {
|
||||
if *kubeconfig == "" {
|
||||
config, err = rest.InClusterConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("create in-cluster client configuration: %v", err)
|
||||
return fmt.Errorf("create in-cluster client configuration: %w", err)
|
||||
}
|
||||
} else {
|
||||
config, err = clientcmd.BuildConfigFromFlags("", *kubeconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create out-of-cluster client configuration: %v", err)
|
||||
return fmt.Errorf("create out-of-cluster client configuration: %w", err)
|
||||
}
|
||||
}
|
||||
config.QPS = *kubeAPIQPS
|
||||
@ -128,7 +128,7 @@ func NewCommand() *cobra.Command {
|
||||
|
||||
clientset, err = kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create client: %v", err)
|
||||
return fmt.Errorf("create client: %w", err)
|
||||
}
|
||||
|
||||
if *httpEndpoint != "" {
|
||||
@ -158,7 +158,7 @@ func NewCommand() *cobra.Command {
|
||||
|
||||
listener, err := net.Listen("tcp", *httpEndpoint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("listen on HTTP endpoint: %v", err)
|
||||
return fmt.Errorf("listen on HTTP endpoint: %w", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
@ -203,12 +203,12 @@ func NewCommand() *cobra.Command {
|
||||
if *resourceConfig != "" {
|
||||
file, err := os.Open(*resourceConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open resource config: %v", err)
|
||||
return fmt.Errorf("open resource config: %w", err)
|
||||
}
|
||||
decoder := json.NewDecoder(file)
|
||||
decoder.DisallowUnknownFields()
|
||||
if err := decoder.Decode(&resources); err != nil {
|
||||
return fmt.Errorf("parse resource config %q: %v", *resourceConfig, err)
|
||||
return fmt.Errorf("parse resource config %q: %w", *resourceConfig, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,7 +230,7 @@ func NewCommand() *cobra.Command {
|
||||
// exceeds the QPS+burst limits.
|
||||
leClientset, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create leaderelection client: %v", err)
|
||||
return fmt.Errorf("create leaderelection client: %w", err)
|
||||
}
|
||||
|
||||
le := leaderelection.New(leClientset, lockName,
|
||||
@ -246,7 +246,7 @@ func NewCommand() *cobra.Command {
|
||||
le.PrepareHealthCheck(mux)
|
||||
}
|
||||
if err := le.Run(); err != nil {
|
||||
return fmt.Errorf("leader election failed: %v", err)
|
||||
return fmt.Errorf("leader election failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -275,10 +275,10 @@ func NewCommand() *cobra.Command {
|
||||
// to know early if there is a setup problem that would prevent
|
||||
// creating those directories.
|
||||
if err := os.MkdirAll(*cdiDir, os.FileMode(0750)); err != nil {
|
||||
return fmt.Errorf("create CDI directory: %v", err)
|
||||
return fmt.Errorf("create CDI directory: %w", err)
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(*endpoint), 0750); err != nil {
|
||||
return fmt.Errorf("create socket directory: %v", err)
|
||||
return fmt.Errorf("create socket directory: %w", err)
|
||||
}
|
||||
|
||||
plugin, err := StartPlugin(logger, *cdiDir, *driverName, "", FileOperations{},
|
||||
@ -287,7 +287,7 @@ func NewCommand() *cobra.Command {
|
||||
kubeletplugin.KubeletPluginSocketPath(*draAddress),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("start example plugin: %v", err)
|
||||
return fmt.Errorf("start example plugin: %w", err)
|
||||
}
|
||||
|
||||
// Handle graceful shutdown. We need to delete Unix domain
|
||||
|
@ -245,7 +245,7 @@ func setupSuite(ctx context.Context) {
|
||||
// #41007. To avoid those pods preventing the whole test runs (and just
|
||||
// wasting the whole run), we allow for some not-ready pods (with the
|
||||
// number equal to the number of allowed not-ready nodes).
|
||||
if err := e2epod.WaitForPodsRunningReady(ctx, c, metav1.NamespaceSystem, int32(framework.TestContext.MinStartupPods), int32(framework.TestContext.AllowedNotReadyNodes), timeouts.SystemPodsStartup, map[string]string{}); err != nil {
|
||||
if err := e2epod.WaitForPodsRunningReady(ctx, c, metav1.NamespaceSystem, int32(framework.TestContext.MinStartupPods), int32(framework.TestContext.AllowedNotReadyNodes), timeouts.SystemPodsStartup); err != nil {
|
||||
e2edebug.DumpAllNamespaceInfo(ctx, c, metav1.NamespaceSystem)
|
||||
e2ekubectl.LogFailedContainers(ctx, c, metav1.NamespaceSystem, framework.Logf)
|
||||
framework.Failf("Error waiting for all pods to be running and ready: %v", err)
|
||||
|
@ -1001,7 +1001,7 @@ func CreateCustomSubresourceInstance(ctx context.Context, namespace, name string
|
||||
}
|
||||
createdObjectMeta, err := meta.Accessor(instance)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error while creating object meta: %v", err)
|
||||
return nil, fmt.Errorf("Error while creating object meta: %w", err)
|
||||
}
|
||||
if len(createdObjectMeta.GetUID()) == 0 {
|
||||
return nil, fmt.Errorf("Missing UUID: %v", instance)
|
||||
|
@ -75,12 +75,12 @@ func CreateDeployment(ctx context.Context, client clientset.Interface, replicas
|
||||
deploymentSpec := testDeployment(replicas, podLabels, nodeSelector, namespace, pvclaims, false, command)
|
||||
deployment, err := client.AppsV1().Deployments(namespace).Create(ctx, deploymentSpec, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("deployment %q Create API error: %v", deploymentSpec.Name, err)
|
||||
return nil, fmt.Errorf("deployment %q Create API error: %w", deploymentSpec.Name, err)
|
||||
}
|
||||
framework.Logf("Waiting deployment %q to complete", deploymentSpec.Name)
|
||||
err = WaitForDeploymentComplete(client, deployment)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("deployment %q failed to complete: %v", deploymentSpec.Name, err)
|
||||
return nil, fmt.Errorf("deployment %q failed to complete: %w", deploymentSpec.Name, err)
|
||||
}
|
||||
return deployment, nil
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func eventOccurred(c clientset.Interface, namespace, eventSelector, msg string)
|
||||
return func(ctx context.Context) (bool, error) {
|
||||
events, err := c.CoreV1().Events(namespace).List(ctx, options)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("got error while getting events: %v", err)
|
||||
return false, fmt.Errorf("got error while getting events: %w", err)
|
||||
}
|
||||
for _, event := range events.Items {
|
||||
if strings.Contains(event.Message, msg) {
|
||||
|
@ -17,12 +17,281 @@ limitations under the License.
|
||||
package framework
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ginkgotypes "github.com/onsi/ginkgo/v2/types"
|
||||
"github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/format"
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
// MakeMatcher builds a gomega.Matcher based on a single callback function.
|
||||
// That function is passed the actual value that is to be checked.
|
||||
// There are three possible outcomes of the check:
|
||||
// - An error is returned, which then is converted into a failure
|
||||
// by Gomega.
|
||||
// - A non-nil failure function is returned, which then is called
|
||||
// by Gomega once a failure string is needed. This is useful
|
||||
// to avoid unnecessarily preparing a failure string for intermediate
|
||||
// failures in Eventually or Consistently.
|
||||
// - Both function and error are nil, which means that the check
|
||||
// succeeded.
|
||||
func MakeMatcher[T interface{}](match func(actual T) (failure func() string, err error)) types.GomegaMatcher {
|
||||
return &matcher[T]{
|
||||
match: match,
|
||||
}
|
||||
}
|
||||
|
||||
type matcher[T interface{}] struct {
|
||||
match func(actual T) (func() string, error)
|
||||
failure func() string
|
||||
}
|
||||
|
||||
func (m *matcher[T]) Match(actual interface{}) (success bool, err error) {
|
||||
if actual, ok := actual.(T); ok {
|
||||
failure, err := m.match(actual)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m.failure = failure
|
||||
if failure != nil {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
var empty T
|
||||
return false, gomega.StopTrying(fmt.Sprintf("internal error: expected %T, got:\n%s", empty, format.Object(actual, 1)))
|
||||
}
|
||||
|
||||
func (m *matcher[T]) FailureMessage(actual interface{}) string {
|
||||
return m.failure()
|
||||
}
|
||||
|
||||
func (m matcher[T]) NegatedFailureMessage(actual interface{}) string {
|
||||
return m.failure()
|
||||
}
|
||||
|
||||
var _ types.GomegaMatcher = &matcher[string]{}
|
||||
|
||||
// Gomega returns an interface that can be used like gomega to express
|
||||
// assertions. The difference is that failed assertions are returned as an
|
||||
// error:
|
||||
//
|
||||
// if err := Gomega().Expect(pod.Status.Phase).To(gomega.BeEqual(v1.Running)); err != nil {
|
||||
// return fmt.Errorf("test pod not running: %w", err)
|
||||
// }
|
||||
//
|
||||
// This error can get wrapped to provide additional context for the
|
||||
// failure. The test then should use ExpectNoError to turn a non-nil error into
|
||||
// a failure.
|
||||
//
|
||||
// When using this approach, there is no need for call offsets and extra
|
||||
// descriptions for the Expect call because the call stack will be dumped when
|
||||
// ExpectNoError is called and the additional description(s) can be added by
|
||||
// wrapping the error.
|
||||
//
|
||||
// Asynchronous assertions use the framework's Poll interval and PodStart timeout
|
||||
// by default.
|
||||
func Gomega() GomegaInstance {
|
||||
return gomegaInstance{}
|
||||
}
|
||||
|
||||
type GomegaInstance interface {
|
||||
Expect(actual interface{}) Assertion
|
||||
Eventually(ctx context.Context, args ...interface{}) AsyncAssertion
|
||||
Consistently(ctx context.Context, args ...interface{}) AsyncAssertion
|
||||
}
|
||||
|
||||
type Assertion interface {
|
||||
Should(matcher types.GomegaMatcher) error
|
||||
ShouldNot(matcher types.GomegaMatcher) error
|
||||
To(matcher types.GomegaMatcher) error
|
||||
ToNot(matcher types.GomegaMatcher) error
|
||||
NotTo(matcher types.GomegaMatcher) error
|
||||
}
|
||||
|
||||
type AsyncAssertion interface {
|
||||
Should(matcher types.GomegaMatcher) error
|
||||
ShouldNot(matcher types.GomegaMatcher) error
|
||||
|
||||
WithTimeout(interval time.Duration) AsyncAssertion
|
||||
WithPolling(interval time.Duration) AsyncAssertion
|
||||
}
|
||||
|
||||
type gomegaInstance struct{}
|
||||
|
||||
var _ GomegaInstance = gomegaInstance{}
|
||||
|
||||
func (g gomegaInstance) Expect(actual interface{}) Assertion {
|
||||
return assertion{actual: actual}
|
||||
}
|
||||
|
||||
func (g gomegaInstance) Eventually(ctx context.Context, args ...interface{}) AsyncAssertion {
|
||||
return newAsyncAssertion(ctx, args, false)
|
||||
}
|
||||
|
||||
func (g gomegaInstance) Consistently(ctx context.Context, args ...interface{}) AsyncAssertion {
|
||||
return newAsyncAssertion(ctx, args, true)
|
||||
}
|
||||
|
||||
func newG() (*FailureError, gomega.Gomega) {
|
||||
var failure FailureError
|
||||
g := gomega.NewGomega(func(msg string, callerSkip ...int) {
|
||||
failure = FailureError{
|
||||
msg: msg,
|
||||
}
|
||||
})
|
||||
|
||||
return &failure, g
|
||||
}
|
||||
|
||||
type assertion struct {
|
||||
actual interface{}
|
||||
}
|
||||
|
||||
func (a assertion) Should(matcher types.GomegaMatcher) error {
|
||||
err, g := newG()
|
||||
if !g.Expect(a.actual).Should(matcher) {
|
||||
err.backtrace()
|
||||
return *err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a assertion) ShouldNot(matcher types.GomegaMatcher) error {
|
||||
err, g := newG()
|
||||
if !g.Expect(a.actual).ShouldNot(matcher) {
|
||||
err.backtrace()
|
||||
return *err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a assertion) To(matcher types.GomegaMatcher) error {
|
||||
err, g := newG()
|
||||
if !g.Expect(a.actual).To(matcher) {
|
||||
err.backtrace()
|
||||
return *err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a assertion) ToNot(matcher types.GomegaMatcher) error {
|
||||
err, g := newG()
|
||||
if !g.Expect(a.actual).ToNot(matcher) {
|
||||
err.backtrace()
|
||||
return *err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a assertion) NotTo(matcher types.GomegaMatcher) error {
|
||||
err, g := newG()
|
||||
if !g.Expect(a.actual).NotTo(matcher) {
|
||||
err.backtrace()
|
||||
return *err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type asyncAssertion struct {
|
||||
ctx context.Context
|
||||
args []interface{}
|
||||
timeout time.Duration
|
||||
interval time.Duration
|
||||
consistently bool
|
||||
}
|
||||
|
||||
func newAsyncAssertion(ctx context.Context, args []interface{}, consistently bool) asyncAssertion {
|
||||
return asyncAssertion{
|
||||
ctx: ctx,
|
||||
args: args,
|
||||
// PodStart is used as default because waiting for a pod is the
|
||||
// most common operation.
|
||||
timeout: TestContext.timeouts.PodStart,
|
||||
interval: TestContext.timeouts.Poll,
|
||||
}
|
||||
}
|
||||
|
||||
func (a asyncAssertion) newAsync() (*FailureError, gomega.AsyncAssertion) {
|
||||
err, g := newG()
|
||||
var assertion gomega.AsyncAssertion
|
||||
if a.consistently {
|
||||
assertion = g.Consistently(a.ctx, a.args...)
|
||||
} else {
|
||||
assertion = g.Eventually(a.ctx, a.args...)
|
||||
}
|
||||
assertion = assertion.WithTimeout(a.timeout).WithPolling(a.interval)
|
||||
return err, assertion
|
||||
}
|
||||
|
||||
func (a asyncAssertion) Should(matcher types.GomegaMatcher) error {
|
||||
err, assertion := a.newAsync()
|
||||
if !assertion.Should(matcher) {
|
||||
err.backtrace()
|
||||
return *err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a asyncAssertion) ShouldNot(matcher types.GomegaMatcher) error {
|
||||
err, assertion := a.newAsync()
|
||||
if !assertion.ShouldNot(matcher) {
|
||||
err.backtrace()
|
||||
return *err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a asyncAssertion) WithTimeout(timeout time.Duration) AsyncAssertion {
|
||||
a.timeout = timeout
|
||||
return a
|
||||
}
|
||||
|
||||
func (a asyncAssertion) WithPolling(interval time.Duration) AsyncAssertion {
|
||||
a.interval = interval
|
||||
return a
|
||||
}
|
||||
|
||||
// FailureError is an error where the error string is meant to be passed to
|
||||
// ginkgo.Fail directly, i.e. adding some prefix like "unexpected error" is not
|
||||
// necessary. It is also not necessary to dump the error struct.
|
||||
type FailureError struct {
|
||||
msg string
|
||||
fullStackTrace string
|
||||
}
|
||||
|
||||
func (f FailureError) Error() string {
|
||||
return f.msg
|
||||
}
|
||||
|
||||
func (f FailureError) Backtrace() string {
|
||||
return f.fullStackTrace
|
||||
}
|
||||
|
||||
func (f FailureError) Is(target error) bool {
|
||||
return target == ErrFailure
|
||||
}
|
||||
|
||||
func (f *FailureError) backtrace() {
|
||||
f.fullStackTrace = ginkgotypes.NewCodeLocationWithStackTrace(2).FullStackTrace
|
||||
}
|
||||
|
||||
// ErrFailure is an empty error that can be wrapped to indicate that an error
|
||||
// is a FailureError. It can also be used to test for a FailureError:.
|
||||
//
|
||||
// return fmt.Errorf("some problem%w", ErrFailure)
|
||||
// ...
|
||||
// err := someOperation()
|
||||
// if errors.Is(err, ErrFailure) {
|
||||
// ...
|
||||
// }
|
||||
var ErrFailure error = FailureError{}
|
||||
|
||||
// ExpectEqual expects the specified two are the same, otherwise an exception raises
|
||||
func ExpectEqual(actual interface{}, extra interface{}, explain ...interface{}) {
|
||||
gomega.ExpectWithOffset(1, actual).To(gomega.Equal(extra), explain...)
|
||||
@ -72,7 +341,17 @@ func ExpectNoErrorWithOffset(offset int, err error, explain ...interface{}) {
|
||||
// failures at the same code line might not be matched in
|
||||
// https://go.k8s.io/triage because the error details are too
|
||||
// different.
|
||||
Logf("Unexpected error: %s\n%s", prefix, format.Object(err, 1))
|
||||
//
|
||||
// Some errors include all relevant information in the Error
|
||||
// string. For those we can skip the redundant log message.
|
||||
// For our own failures we only log the additional stack backtrace
|
||||
// because it is not included in the failure message.
|
||||
var failure FailureError
|
||||
if errors.As(err, &failure) && failure.Backtrace() != "" {
|
||||
Logf("Failed inside E2E framework:\n %s", strings.ReplaceAll(failure.Backtrace(), "\n", "\n "))
|
||||
} else if !errors.Is(err, ErrFailure) {
|
||||
Logf("Unexpected error: %s\n%s", prefix, format.Object(err, 1))
|
||||
}
|
||||
Fail(prefix+err.Error(), 1+offset)
|
||||
}
|
||||
|
||||
|
62
test/e2e/framework/expect_test.go
Normal file
62
test/e2e/framework/expect_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2023 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 framework
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/onsi/gomega"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// This test is sensitive to line numbering.
|
||||
// The following lines can be removed to compensate for import changes.
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// This must be line #40.
|
||||
|
||||
func TestNewGomega(t *testing.T) {
|
||||
if err := Gomega().Expect("hello").To(gomega.Equal("hello")); err != nil {
|
||||
t.Errorf("unexpected failure: %s", err.Error())
|
||||
}
|
||||
err := Gomega().Expect("hello").ToNot(gomega.Equal("hello"))
|
||||
require.NotNil(t, err)
|
||||
assert.Equal(t, `Expected
|
||||
<string>: hello
|
||||
not to equal
|
||||
<string>: hello`, err.Error())
|
||||
if !errors.Is(err, ErrFailure) {
|
||||
t.Errorf("expected error that is ErrFailure, got %T: %+v", err, err)
|
||||
}
|
||||
var failure FailureError
|
||||
if !errors.As(err, &failure) {
|
||||
t.Errorf("expected error that can be copied to FailureError, got %T: %+v", err, err)
|
||||
} else {
|
||||
assert.Regexp(t, `^k8s.io/kubernetes/test/e2e/framework.TestNewGomega\(0x[0-9A-Fa-f]*\)
|
||||
.*/test/e2e/framework/expect_test.go:46`, failure.Backtrace())
|
||||
}
|
||||
}
|
@ -34,6 +34,9 @@ type GetFunc[T any] func(ctx context.Context) (T, error)
|
||||
// APIGetFunc is a get functions as used in client-go.
|
||||
type APIGetFunc[T any] func(ctx context.Context, name string, getOptions metav1.GetOptions) (T, error)
|
||||
|
||||
// APIListFunc is a list functions as used in client-go.
|
||||
type APIListFunc[T any] func(ctx context.Context, listOptions metav1.ListOptions) (T, error)
|
||||
|
||||
// GetObject takes a get function like clientset.CoreV1().Pods(ns).Get
|
||||
// and the parameters for it and returns a function that executes that get
|
||||
// operation in a [gomega.Eventually] or [gomega.Consistently].
|
||||
@ -47,6 +50,17 @@ func GetObject[T any](get APIGetFunc[T], name string, getOptions metav1.GetOptio
|
||||
})
|
||||
}
|
||||
|
||||
// ListObjects takes a list function like clientset.CoreV1().Pods(ns).List
|
||||
// and the parameters for it and returns a function that executes that list
|
||||
// operation in a [gomega.Eventually] or [gomega.Consistently].
|
||||
//
|
||||
// Delays and retries are handled by [HandleRetry].
|
||||
func ListObjects[T any](list APIListFunc[T], listOptions metav1.ListOptions) GetFunc[T] {
|
||||
return HandleRetry(func(ctx context.Context) (T, error) {
|
||||
return list(ctx, listOptions)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleRetry wraps an arbitrary get function. When the wrapped function
|
||||
// returns an error, HandleGetError will decide whether the call should be
|
||||
// retried and if requested, will sleep before doing so.
|
||||
|
@ -309,7 +309,7 @@ func GenerateRSACerts(host string, isCA bool) ([]byte, []byte, error) {
|
||||
}
|
||||
priv, err := rsa.GenerateKey(rand.Reader, rsaBits)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Failed to generate key: %v", err)
|
||||
return nil, nil, fmt.Errorf("Failed to generate key: %w", err)
|
||||
}
|
||||
notBefore := time.Now()
|
||||
notAfter := notBefore.Add(validFor)
|
||||
@ -318,7 +318,7 @@ func GenerateRSACerts(host string, isCA bool) ([]byte, []byte, error) {
|
||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to generate serial number: %s", err)
|
||||
return nil, nil, fmt.Errorf("failed to generate serial number: %w", err)
|
||||
}
|
||||
template := x509.Certificate{
|
||||
SerialNumber: serialNumber,
|
||||
@ -351,13 +351,13 @@ func GenerateRSACerts(host string, isCA bool) ([]byte, []byte, error) {
|
||||
var keyOut, certOut bytes.Buffer
|
||||
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Failed to create certificate: %s", err)
|
||||
return nil, nil, fmt.Errorf("Failed to create certificate: %w", err)
|
||||
}
|
||||
if err := pem.Encode(&certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
|
||||
return nil, nil, fmt.Errorf("Failed creating cert: %v", err)
|
||||
return nil, nil, fmt.Errorf("Failed creating cert: %w", err)
|
||||
}
|
||||
if err := pem.Encode(&keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
|
||||
return nil, nil, fmt.Errorf("Failed creating key: %v", err)
|
||||
return nil, nil, fmt.Errorf("Failed creating key: %w", err)
|
||||
}
|
||||
return certOut.Bytes(), keyOut.Bytes(), nil
|
||||
}
|
||||
@ -532,11 +532,11 @@ func ingressFromManifest(fileName string) (*networkingv1.Ingress, error) {
|
||||
func ingressToManifest(ing *networkingv1.Ingress, path string) error {
|
||||
serialized, err := marshalToYaml(ing, networkingv1.SchemeGroupVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal ingress %v to YAML: %v", ing, err)
|
||||
return fmt.Errorf("failed to marshal ingress %v to YAML: %w", ing, err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(path, serialized, 0600); err != nil {
|
||||
return fmt.Errorf("error in writing ingress to file: %s", err)
|
||||
return fmt.Errorf("error in writing ingress to file: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -1150,17 +1150,17 @@ func (j *TestJig) DeleteTestResource(ctx context.Context, cs clientset.Interface
|
||||
var errs []error
|
||||
if ing != nil {
|
||||
if err := j.runDelete(ctx, ing); err != nil {
|
||||
errs = append(errs, fmt.Errorf("error while deleting ingress %s/%s: %v", ing.Namespace, ing.Name, err))
|
||||
errs = append(errs, fmt.Errorf("error while deleting ingress %s/%s: %w", ing.Namespace, ing.Name, err))
|
||||
}
|
||||
}
|
||||
if svc != nil {
|
||||
if err := cs.CoreV1().Services(svc.Namespace).Delete(ctx, svc.Name, metav1.DeleteOptions{}); err != nil {
|
||||
errs = append(errs, fmt.Errorf("error while deleting service %s/%s: %v", svc.Namespace, svc.Name, err))
|
||||
errs = append(errs, fmt.Errorf("error while deleting service %s/%s: %w", svc.Namespace, svc.Name, err))
|
||||
}
|
||||
}
|
||||
if deploy != nil {
|
||||
if err := cs.AppsV1().Deployments(deploy.Namespace).Delete(ctx, deploy.Name, metav1.DeleteOptions{}); err != nil {
|
||||
errs = append(errs, fmt.Errorf("error while deleting deployment %s/%s: %v", deploy.Namespace, deploy.Name, err))
|
||||
errs = append(errs, fmt.Errorf("error while deleting deployment %s/%s: %w", deploy.Namespace, deploy.Name, err))
|
||||
}
|
||||
}
|
||||
return errs
|
||||
|
@ -122,6 +122,9 @@ var timePrefix = regexp.MustCompile(`(?m)^[[:alpha:]]{3} +[[:digit:]]{1,2} +[[:d
|
||||
// elapsedSuffix matches "Elapsed: 16.189µs"
|
||||
var elapsedSuffix = regexp.MustCompile(`Elapsed: [[:digit:]]+(\.[[:digit:]]+)?(µs|ns|ms|s|m)`)
|
||||
|
||||
// afterSuffix matches "after 5.001s."
|
||||
var afterSuffix = regexp.MustCompile(`after [[:digit:]]+(\.[[:digit:]]+)?(µs|ns|ms|s|m).`)
|
||||
|
||||
// timeSuffix matches "@ 09/06/22 15:36:43.44 (5.001s)" as printed by Ginkgo v2 for log output, with the duration being optional.
|
||||
var timeSuffix = regexp.MustCompile(`(?m)@[[:space:]][[:digit:]]{2}/[[:digit:]]{2}/[[:digit:]]{2} [[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}(\.[[:digit:]]{1,3})?( \([[:digit:]]+(\.[[:digit:]]+)?(µs|ns|ms|s|m)\))?$`)
|
||||
|
||||
@ -129,6 +132,7 @@ func stripTimes(in string) string {
|
||||
out := timePrefix.ReplaceAllString(in, "")
|
||||
out = elapsedSuffix.ReplaceAllString(out, "Elapsed: <elapsed>")
|
||||
out = timeSuffix.ReplaceAllString(out, "<time>")
|
||||
out = afterSuffix.ReplaceAllString(out, "after <after>.")
|
||||
return out
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ func RestartControllerManager(ctx context.Context) error {
|
||||
result, err := e2essh.SSH(ctx, cmd, net.JoinHostPort(framework.APIAddress(), e2essh.SSHPort), framework.TestContext.Provider)
|
||||
if err != nil || result.Code != 0 {
|
||||
e2essh.LogResult(result)
|
||||
return fmt.Errorf("couldn't restart controller-manager: %v", err)
|
||||
return fmt.Errorf("couldn't restart controller-manager: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ func DaemonSetFromURL(ctx context.Context, url string) (*appsv1.DaemonSet, error
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to get url: %v", err)
|
||||
return nil, fmt.Errorf("Failed to get url: %w", err)
|
||||
}
|
||||
if response.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("invalid http response status: %v", response.StatusCode)
|
||||
@ -124,7 +124,7 @@ func DaemonSetFromURL(ctx context.Context, url string) (*appsv1.DaemonSet, error
|
||||
|
||||
data, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to read html response body: %v", err)
|
||||
return nil, fmt.Errorf("Failed to read html response body: %w", err)
|
||||
}
|
||||
return DaemonSetFromData(data)
|
||||
}
|
||||
@ -134,12 +134,12 @@ func DaemonSetFromData(data []byte) (*appsv1.DaemonSet, error) {
|
||||
var ds appsv1.DaemonSet
|
||||
dataJSON, err := utilyaml.ToJSON(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse data to json: %v", err)
|
||||
return nil, fmt.Errorf("Failed to parse data to json: %w", err)
|
||||
}
|
||||
|
||||
err = runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), dataJSON, &ds)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to decode DaemonSet spec: %v", err)
|
||||
return nil, fmt.Errorf("Failed to decode DaemonSet spec: %w", err)
|
||||
}
|
||||
return &ds, nil
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
@ -889,7 +888,7 @@ func (config *NetworkingTestConfig) DeleteNetProxyPod(ctx context.Context) {
|
||||
framework.ExpectNoError(config.getPodClient().Delete(ctx, pod.Name, *metav1.NewDeleteOptions(0)))
|
||||
config.EndpointPods = config.EndpointPods[1:]
|
||||
// wait for pod being deleted.
|
||||
err := e2epod.WaitForPodToDisappear(ctx, config.f.ClientSet, config.Namespace, pod.Name, labels.Everything(), time.Second, wait.ForeverTestTimeout)
|
||||
err := e2epod.WaitForPodNotFoundInNamespace(ctx, config.f.ClientSet, config.Namespace, pod.Name, wait.ForeverTestTimeout)
|
||||
if err != nil {
|
||||
framework.Failf("Failed to delete %s pod: %v", pod.Name, err)
|
||||
}
|
||||
@ -1027,7 +1026,7 @@ func PokeHTTP(host string, port int, path string, params *HTTPPokeParams) HTTPPo
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
ret.Status = HTTPError
|
||||
ret.Error = fmt.Errorf("error reading HTTP body: %v", err)
|
||||
ret.Error = fmt.Errorf("error reading HTTP body: %w", err)
|
||||
framework.Logf("Poke(%q): %v", url, ret.Error)
|
||||
return ret
|
||||
}
|
||||
@ -1192,7 +1191,7 @@ func WaitForService(ctx context.Context, c clientset.Interface, namespace, name
|
||||
})
|
||||
if err != nil {
|
||||
stateMsg := map[bool]string{true: "to appear", false: "to disappear"}
|
||||
return fmt.Errorf("error waiting for service %s/%s %s: %v", namespace, name, stateMsg[exist], err)
|
||||
return fmt.Errorf("error waiting for service %s/%s %s: %w", namespace, name, stateMsg[exist], err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ func NodeHasTaint(ctx context.Context, c clientset.Interface, nodeName string, t
|
||||
// default test add-ons.
|
||||
func AllNodesReady(ctx context.Context, c clientset.Interface, timeout time.Duration) error {
|
||||
if err := allNodesReady(ctx, c, timeout); err != nil {
|
||||
return fmt.Errorf("checking for ready nodes: %v", err)
|
||||
return fmt.Errorf("checking for ready nodes: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ func CollectAddresses(nodes *v1.NodeList, addressType v1.NodeAddressType) []stri
|
||||
func PickIP(ctx context.Context, c clientset.Interface) (string, error) {
|
||||
publicIps, err := GetPublicIps(ctx, c)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("get node public IPs error: %s", err)
|
||||
return "", fmt.Errorf("get node public IPs error: %w", err)
|
||||
}
|
||||
if len(publicIps) == 0 {
|
||||
return "", fmt.Errorf("got unexpected number (%d) of public IPs", len(publicIps))
|
||||
@ -309,7 +309,7 @@ func PickIP(ctx context.Context, c clientset.Interface) (string, error) {
|
||||
func GetPublicIps(ctx context.Context, c clientset.Interface) ([]string, error) {
|
||||
nodes, err := GetReadySchedulableNodes(ctx, c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get schedulable and ready nodes error: %s", err)
|
||||
return nil, fmt.Errorf("get schedulable and ready nodes error: %w", err)
|
||||
}
|
||||
ips := CollectAddresses(nodes, v1.NodeExternalIP)
|
||||
if len(ips) == 0 {
|
||||
@ -327,7 +327,7 @@ func GetPublicIps(ctx context.Context, c clientset.Interface) ([]string, error)
|
||||
func GetReadySchedulableNodes(ctx context.Context, c clientset.Interface) (nodes *v1.NodeList, err error) {
|
||||
nodes, err = checkWaitListSchedulableNodes(ctx, c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listing schedulable nodes error: %s", err)
|
||||
return nil, fmt.Errorf("listing schedulable nodes error: %w", err)
|
||||
}
|
||||
Filter(nodes, func(node v1.Node) bool {
|
||||
return IsNodeSchedulable(&node) && isNodeUntainted(&node)
|
||||
@ -376,7 +376,7 @@ func GetRandomReadySchedulableNode(ctx context.Context, c clientset.Interface) (
|
||||
func GetReadyNodesIncludingTainted(ctx context.Context, c clientset.Interface) (nodes *v1.NodeList, err error) {
|
||||
nodes, err = checkWaitListSchedulableNodes(ctx, c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listing schedulable nodes error: %s", err)
|
||||
return nil, fmt.Errorf("listing schedulable nodes error: %w", err)
|
||||
}
|
||||
Filter(nodes, func(node v1.Node) bool {
|
||||
return IsNodeSchedulable(&node)
|
||||
@ -536,7 +536,7 @@ func PodNodePairs(ctx context.Context, c clientset.Interface, ns string) ([]PodN
|
||||
func GetClusterZones(ctx context.Context, c clientset.Interface) (sets.String, error) {
|
||||
nodes, err := c.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error getting nodes while attempting to list cluster zones: %v", err)
|
||||
return nil, fmt.Errorf("Error getting nodes while attempting to list cluster zones: %w", err)
|
||||
}
|
||||
|
||||
// collect values of zone label from all nodes
|
||||
@ -558,7 +558,7 @@ func GetSchedulableClusterZones(ctx context.Context, c clientset.Interface) (set
|
||||
// GetReadySchedulableNodes already filters our tainted and unschedulable nodes.
|
||||
nodes, err := GetReadySchedulableNodes(ctx, c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting nodes while attempting to list cluster zones: %v", err)
|
||||
return nil, fmt.Errorf("error getting nodes while attempting to list cluster zones: %w", err)
|
||||
}
|
||||
|
||||
// collect values of zone label from all nodes
|
||||
@ -781,7 +781,7 @@ func removeNodeTaint(ctx context.Context, c clientset.Interface, nodeName string
|
||||
func patchNodeTaints(ctx context.Context, c clientset.Interface, nodeName string, oldNode *v1.Node, newNode *v1.Node) error {
|
||||
oldData, err := json.Marshal(oldNode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal old node %#v for node %q: %v", oldNode, nodeName, err)
|
||||
return fmt.Errorf("failed to marshal old node %#v for node %q: %w", oldNode, nodeName, err)
|
||||
}
|
||||
|
||||
newTaints := newNode.Spec.Taints
|
||||
@ -789,12 +789,12 @@ func patchNodeTaints(ctx context.Context, c clientset.Interface, nodeName string
|
||||
newNodeClone.Spec.Taints = newTaints
|
||||
newData, err := json.Marshal(newNodeClone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal new node %#v for node %q: %v", newNodeClone, nodeName, err)
|
||||
return fmt.Errorf("failed to marshal new node %#v for node %q: %w", newNodeClone, nodeName, err)
|
||||
}
|
||||
|
||||
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create patch for node %q: %v", nodeName, err)
|
||||
return fmt.Errorf("failed to create patch for node %q: %w", nodeName, err)
|
||||
}
|
||||
|
||||
_, err = c.CoreV1().Nodes().Patch(ctx, nodeName, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{})
|
||||
|
@ -56,17 +56,17 @@ func CreateUnschedulablePod(ctx context.Context, client clientset.Interface, nam
|
||||
pod := MakePod(namespace, nodeSelector, pvclaims, isPrivileged, command)
|
||||
pod, err := client.CoreV1().Pods(namespace).Create(ctx, pod, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pod Create API error: %v", err)
|
||||
return nil, fmt.Errorf("pod Create API error: %w", err)
|
||||
}
|
||||
// Waiting for pod to become Unschedulable
|
||||
err = WaitForPodNameUnschedulableInNamespace(ctx, client, pod.Name, namespace)
|
||||
if err != nil {
|
||||
return pod, fmt.Errorf("pod %q is not Unschedulable: %v", pod.Name, err)
|
||||
return pod, fmt.Errorf("pod %q is not Unschedulable: %w", pod.Name, err)
|
||||
}
|
||||
// get fresh pod info
|
||||
pod, err = client.CoreV1().Pods(namespace).Get(ctx, pod.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return pod, fmt.Errorf("pod Get API error: %v", err)
|
||||
return pod, fmt.Errorf("pod Get API error: %w", err)
|
||||
}
|
||||
return pod, nil
|
||||
}
|
||||
@ -81,17 +81,17 @@ func CreatePod(ctx context.Context, client clientset.Interface, namespace string
|
||||
pod := MakePod(namespace, nodeSelector, pvclaims, isPrivileged, command)
|
||||
pod, err := client.CoreV1().Pods(namespace).Create(ctx, pod, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pod Create API error: %v", err)
|
||||
return nil, fmt.Errorf("pod Create API error: %w", err)
|
||||
}
|
||||
// Waiting for pod to be running
|
||||
err = WaitForPodNameRunningInNamespace(ctx, client, pod.Name, namespace)
|
||||
if err != nil {
|
||||
return pod, fmt.Errorf("pod %q is not Running: %v", pod.Name, err)
|
||||
return pod, fmt.Errorf("pod %q is not Running: %w", pod.Name, err)
|
||||
}
|
||||
// get fresh pod info
|
||||
pod, err = client.CoreV1().Pods(namespace).Get(ctx, pod.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return pod, fmt.Errorf("pod Get API error: %v", err)
|
||||
return pod, fmt.Errorf("pod Get API error: %w", err)
|
||||
}
|
||||
return pod, nil
|
||||
}
|
||||
@ -105,23 +105,23 @@ func CreateSecPod(ctx context.Context, client clientset.Interface, podConfig *Co
|
||||
func CreateSecPodWithNodeSelection(ctx context.Context, client clientset.Interface, podConfig *Config, timeout time.Duration) (*v1.Pod, error) {
|
||||
pod, err := MakeSecPod(podConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to create pod: %v", err)
|
||||
return nil, fmt.Errorf("Unable to create pod: %w", err)
|
||||
}
|
||||
|
||||
pod, err = client.CoreV1().Pods(podConfig.NS).Create(ctx, pod, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pod Create API error: %v", err)
|
||||
return nil, fmt.Errorf("pod Create API error: %w", err)
|
||||
}
|
||||
|
||||
// Waiting for pod to be running
|
||||
err = WaitTimeoutForPodRunningInNamespace(ctx, client, pod.Name, podConfig.NS, timeout)
|
||||
if err != nil {
|
||||
return pod, fmt.Errorf("pod %q is not Running: %v", pod.Name, err)
|
||||
return pod, fmt.Errorf("pod %q is not Running: %w", pod.Name, err)
|
||||
}
|
||||
// get fresh pod info
|
||||
pod, err = client.CoreV1().Pods(podConfig.NS).Get(ctx, pod.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return pod, fmt.Errorf("pod Get API error: %v", err)
|
||||
return pod, fmt.Errorf("pod Get API error: %w", err)
|
||||
}
|
||||
return pod, nil
|
||||
}
|
||||
|
@ -65,12 +65,12 @@ func DeletePodWithWaitByName(ctx context.Context, c clientset.Interface, podName
|
||||
if apierrors.IsNotFound(err) {
|
||||
return nil // assume pod was already deleted
|
||||
}
|
||||
return fmt.Errorf("pod Delete API error: %v", err)
|
||||
return fmt.Errorf("pod Delete API error: %w", err)
|
||||
}
|
||||
framework.Logf("Wait up to %v for pod %q to be fully deleted", PodDeleteTimeout, podName)
|
||||
err = WaitForPodNotFoundInNamespace(ctx, c, podName, podNamespace, PodDeleteTimeout)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pod %q was not deleted: %v", podName, err)
|
||||
return fmt.Errorf("pod %q was not deleted: %w", podName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -98,7 +98,7 @@ func DeletePodWithGracePeriodByName(ctx context.Context, c clientset.Interface,
|
||||
if apierrors.IsNotFound(err) {
|
||||
return nil // assume pod was already deleted
|
||||
}
|
||||
return fmt.Errorf("pod Delete API error: %v", err)
|
||||
return fmt.Errorf("pod Delete API error: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -87,13 +87,13 @@ func (d *Dialer) DialContainerPort(ctx context.Context, addr Addr) (conn net.Con
|
||||
SubResource("portforward")
|
||||
transport, upgrader, err := spdy.RoundTripperFor(restConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create round tripper: %v", err)
|
||||
return nil, fmt.Errorf("create round tripper: %w", err)
|
||||
}
|
||||
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", req.URL())
|
||||
|
||||
streamConn, _, err := dialer.Dial(portforward.PortForwardProtocolV1Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("dialer failed: %v", err)
|
||||
return nil, fmt.Errorf("dialer failed: %w", err)
|
||||
}
|
||||
requestID := "1"
|
||||
defer func() {
|
||||
@ -112,7 +112,7 @@ func (d *Dialer) DialContainerPort(ctx context.Context, addr Addr) (conn net.Con
|
||||
// This happens asynchronously.
|
||||
errorStream, err := streamConn.CreateStream(headers)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating error stream: %v", err)
|
||||
return nil, fmt.Errorf("error creating error stream: %w", err)
|
||||
}
|
||||
errorStream.Close()
|
||||
go func() {
|
||||
@ -129,7 +129,7 @@ func (d *Dialer) DialContainerPort(ctx context.Context, addr Addr) (conn net.Con
|
||||
headers.Set(v1.StreamType, v1.StreamTypeData)
|
||||
dataStream, err := streamConn.CreateStream(headers)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating data stream: %v", err)
|
||||
return nil, fmt.Errorf("error creating data stream: %w", err)
|
||||
}
|
||||
|
||||
return &stream{
|
||||
|
@ -107,7 +107,7 @@ func RunHostCmdWithRetries(ns, name, cmd string, interval, timeout time.Duration
|
||||
return out, nil
|
||||
}
|
||||
if elapsed := time.Since(start); elapsed > timeout {
|
||||
return out, fmt.Errorf("RunHostCmd still failed after %v: %v", elapsed, err)
|
||||
return out, fmt.Errorf("RunHostCmd still failed after %v: %w", elapsed, err)
|
||||
}
|
||||
framework.Logf("Waiting %v to retry failed RunHostCmd: %v", interval, err)
|
||||
time.Sleep(interval)
|
||||
@ -166,7 +166,7 @@ func MatchContainerOutput(
|
||||
// Grab its logs. Get host first.
|
||||
podStatus, err := podClient.Get(ctx, createdPod.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get pod status: %v", err)
|
||||
return fmt.Errorf("failed to get pod status: %w", err)
|
||||
}
|
||||
|
||||
if podErr != nil {
|
||||
@ -192,14 +192,14 @@ func MatchContainerOutput(
|
||||
if err != nil {
|
||||
framework.Logf("Failed to get logs from node %q pod %q container %q. %v",
|
||||
podStatus.Spec.NodeName, podStatus.Name, containerName, err)
|
||||
return fmt.Errorf("failed to get logs from %s for %s: %v", podStatus.Name, containerName, err)
|
||||
return fmt.Errorf("failed to get logs from %s for %s: %w", podStatus.Name, containerName, err)
|
||||
}
|
||||
|
||||
for _, expected := range expectedOutput {
|
||||
m := matcher(expected)
|
||||
matches, err := m.Match(logs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("expected %q in container output: %v", expected, err)
|
||||
return fmt.Errorf("expected %q in container output: %w", expected, err)
|
||||
} else if !matches {
|
||||
return fmt.Errorf("expected %q in container output: %s", expected, m.FailureMessage(logs))
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||
@ -134,7 +133,7 @@ func (c *PodClient) Update(ctx context.Context, name string, updateFn func(pod *
|
||||
framework.ExpectNoError(wait.PollWithContext(ctx, time.Millisecond*500, time.Second*30, func(ctx context.Context) (bool, error) {
|
||||
pod, err := c.PodInterface.Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get pod %q: %v", name, err)
|
||||
return false, fmt.Errorf("failed to get pod %q: %w", name, err)
|
||||
}
|
||||
updateFn(pod)
|
||||
_, err = c.PodInterface.Update(ctx, pod, metav1.UpdateOptions{})
|
||||
@ -146,7 +145,7 @@ func (c *PodClient) Update(ctx context.Context, name string, updateFn func(pod *
|
||||
framework.Logf("Conflicting update to pod %q, re-get and re-update: %v", name, err)
|
||||
return false, nil
|
||||
}
|
||||
return false, fmt.Errorf("failed to update pod %q: %v", name, err)
|
||||
return false, fmt.Errorf("failed to update pod %q: %w", name, err)
|
||||
}))
|
||||
}
|
||||
|
||||
@ -182,8 +181,7 @@ func (c *PodClient) DeleteSync(ctx context.Context, name string, options metav1.
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
framework.Failf("Failed to delete pod %q: %v", name, err)
|
||||
}
|
||||
gomega.Expect(WaitForPodToDisappear(ctx, c.f.ClientSet, namespace, name, labels.Everything(),
|
||||
2*time.Second, timeout)).To(gomega.Succeed(), "wait for pod %q to disappear", name)
|
||||
framework.ExpectNoError(WaitForPodNotFoundInNamespace(ctx, c.f.ClientSet, namespace, name, timeout), "wait for pod %q to disappear", name)
|
||||
}
|
||||
|
||||
// mungeSpec apply test-suite specific transformations to the pod spec.
|
||||
@ -263,7 +261,7 @@ func (c *PodClient) WaitForErrorEventOrSuccess(ctx context.Context, pod *v1.Pod)
|
||||
err := wait.PollWithContext(ctx, framework.Poll, framework.PodStartTimeout, func(ctx context.Context) (bool, error) {
|
||||
evnts, err := c.f.ClientSet.CoreV1().Events(pod.Namespace).Search(scheme.Scheme, pod)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error in listing events: %s", err)
|
||||
return false, fmt.Errorf("error in listing events: %w", err)
|
||||
}
|
||||
for _, e := range evnts.Items {
|
||||
switch e.Reason {
|
||||
@ -290,7 +288,7 @@ func (c *PodClient) MatchContainerOutput(ctx context.Context, name string, conta
|
||||
}
|
||||
regex, err := regexp.Compile(expectedRegexp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to compile regexp %q: %v", expectedRegexp, err)
|
||||
return fmt.Errorf("failed to compile regexp %q: %w", expectedRegexp, err)
|
||||
}
|
||||
if !regex.MatchString(output) {
|
||||
return fmt.Errorf("failed to match regexp %q in output %q", expectedRegexp, output)
|
||||
|
@ -18,7 +18,6 @@ package pod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -31,7 +30,6 @@ import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
@ -40,14 +38,6 @@ import (
|
||||
imageutils "k8s.io/kubernetes/test/utils/image"
|
||||
)
|
||||
|
||||
// errPodCompleted is returned by PodRunning or PodContainerRunning to indicate that
|
||||
// the pod has already reached completed state.
|
||||
var errPodCompleted = FinalError(errors.New("pod ran to completion successfully"))
|
||||
|
||||
// errPodFailed is returned by PodRunning or PodContainerRunning to indicate that
|
||||
// the pod has already reached a permanent failue state.
|
||||
var errPodFailed = FinalError(errors.New("pod failed permanently"))
|
||||
|
||||
// LabelLogOnPodFailure can be used to mark which Pods will have their logs logged in the case of
|
||||
// a test failure. By default, if there are no Pods with this label, only the first 5 Pods will
|
||||
// have their logs fetched.
|
||||
@ -69,95 +59,6 @@ func expectNoErrorWithOffset(offset int, err error, explain ...interface{}) {
|
||||
gomega.ExpectWithOffset(1+offset, err).NotTo(gomega.HaveOccurred(), explain...)
|
||||
}
|
||||
|
||||
func isElementOf(podUID types.UID, pods *v1.PodList) bool {
|
||||
for _, pod := range pods.Items {
|
||||
if pod.UID == podUID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ProxyResponseChecker is a context for checking pods responses by issuing GETs to them (via the API
|
||||
// proxy) and verifying that they answer with their own pod name.
|
||||
type ProxyResponseChecker struct {
|
||||
c clientset.Interface
|
||||
ns string
|
||||
label labels.Selector
|
||||
controllerName string
|
||||
respondName bool // Whether the pod should respond with its own name.
|
||||
pods *v1.PodList
|
||||
}
|
||||
|
||||
// NewProxyResponseChecker returns a context for checking pods responses.
|
||||
func NewProxyResponseChecker(c clientset.Interface, ns string, label labels.Selector, controllerName string, respondName bool, pods *v1.PodList) ProxyResponseChecker {
|
||||
return ProxyResponseChecker{c, ns, label, controllerName, respondName, pods}
|
||||
}
|
||||
|
||||
// CheckAllResponses issues GETs to all pods in the context and verify they
|
||||
// reply with their own pod name.
|
||||
func (r ProxyResponseChecker) CheckAllResponses(ctx context.Context) (done bool, err error) {
|
||||
successes := 0
|
||||
options := metav1.ListOptions{LabelSelector: r.label.String()}
|
||||
currentPods, err := r.c.CoreV1().Pods(r.ns).List(ctx, options)
|
||||
expectNoError(err, "Failed to get list of currentPods in namespace: %s", r.ns)
|
||||
for i, pod := range r.pods.Items {
|
||||
// Check that the replica list remains unchanged, otherwise we have problems.
|
||||
if !isElementOf(pod.UID, currentPods) {
|
||||
return false, fmt.Errorf("pod with UID %s is no longer a member of the replica set. Must have been restarted for some reason. Current replica set: %v", pod.UID, currentPods)
|
||||
}
|
||||
|
||||
ctxUntil, cancel := context.WithTimeout(ctx, singleCallTimeout)
|
||||
defer cancel()
|
||||
|
||||
body, err := r.c.CoreV1().RESTClient().Get().
|
||||
Namespace(r.ns).
|
||||
Resource("pods").
|
||||
SubResource("proxy").
|
||||
Name(string(pod.Name)).
|
||||
Do(ctxUntil).
|
||||
Raw()
|
||||
|
||||
if err != nil {
|
||||
if ctxUntil.Err() != nil {
|
||||
// We may encounter errors here because of a race between the pod readiness and apiserver
|
||||
// proxy. So, we log the error and retry if this occurs.
|
||||
framework.Logf("Controller %s: Failed to Get from replica %d [%s]: %v\n pod status: %#v", r.controllerName, i+1, pod.Name, err, pod.Status)
|
||||
return false, nil
|
||||
}
|
||||
framework.Logf("Controller %s: Failed to GET from replica %d [%s]: %v\npod status: %#v", r.controllerName, i+1, pod.Name, err, pod.Status)
|
||||
continue
|
||||
}
|
||||
// The response checker expects the pod's name unless !respondName, in
|
||||
// which case it just checks for a non-empty response.
|
||||
got := string(body)
|
||||
what := ""
|
||||
if r.respondName {
|
||||
what = "expected"
|
||||
want := pod.Name
|
||||
if got != want {
|
||||
framework.Logf("Controller %s: Replica %d [%s] expected response %q but got %q",
|
||||
r.controllerName, i+1, pod.Name, want, got)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
what = "non-empty"
|
||||
if len(got) == 0 {
|
||||
framework.Logf("Controller %s: Replica %d [%s] expected non-empty response",
|
||||
r.controllerName, i+1, pod.Name)
|
||||
continue
|
||||
}
|
||||
}
|
||||
successes++
|
||||
framework.Logf("Controller %s: Got %s result from replica %d [%s]: %q, %d of %d required successes so far",
|
||||
r.controllerName, what, i+1, pod.Name, got, successes, len(r.pods.Items))
|
||||
}
|
||||
if successes < len(r.pods.Items) {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// PodsCreated returns a pod list matched by the given name.
|
||||
func PodsCreated(ctx context.Context, c clientset.Interface, ns, name string, replicas int32) (*v1.PodList, error) {
|
||||
label := labels.SelectorFromSet(labels.Set(map[string]string{"name": name}))
|
||||
@ -213,10 +114,7 @@ func podRunningMaybeResponding(ctx context.Context, c clientset.Interface, ns, n
|
||||
return fmt.Errorf("failed to wait for pods running: %v", e)
|
||||
}
|
||||
if checkResponding {
|
||||
err = PodsResponding(ctx, c, ns, name, wantName, pods)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to wait for pods responding: %v", err)
|
||||
}
|
||||
return WaitForPodsResponding(ctx, c, ns, name, wantName, podRespondingTimeout, pods)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -635,7 +533,7 @@ func VerifyPodHasConditionWithType(ctx context.Context, f *framework.Framework,
|
||||
func getNodeTTLAnnotationValue(ctx context.Context, c clientset.Interface) (time.Duration, error) {
|
||||
nodes, err := c.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
|
||||
if err != nil || len(nodes.Items) == 0 {
|
||||
return time.Duration(0), fmt.Errorf("Couldn't list any nodes to get TTL annotation: %v", err)
|
||||
return time.Duration(0), fmt.Errorf("Couldn't list any nodes to get TTL annotation: %w", err)
|
||||
}
|
||||
// Since TTL the kubelet is using is stored in node object, for the timeout
|
||||
// purpose we take it from the first node (all of them should be the same).
|
||||
@ -674,15 +572,3 @@ func IsPodActive(p *v1.Pod) bool {
|
||||
v1.PodFailed != p.Status.Phase &&
|
||||
p.DeletionTimestamp == nil
|
||||
}
|
||||
|
||||
func podIdentifier(namespace, name string) string {
|
||||
return fmt.Sprintf("%s/%s", namespace, name)
|
||||
}
|
||||
|
||||
func identifier(pod *v1.Pod) string {
|
||||
id := podIdentifier(pod.Namespace, pod.Name)
|
||||
if pod.UID != "" {
|
||||
id += fmt.Sprintf("(%s)", pod.UID)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
@ -17,12 +17,11 @@ limitations under the License.
|
||||
package pod
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"text/tabwriter"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/v2"
|
||||
@ -30,15 +29,18 @@ import (
|
||||
"github.com/onsi/gomega/gcustom"
|
||||
"github.com/onsi/gomega/types"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
apitypes "k8s.io/apimachinery/pkg/types"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/kubectl/pkg/util/podutils"
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
testutils "k8s.io/kubernetes/test/utils"
|
||||
"k8s.io/kubernetes/test/utils/format"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -66,108 +68,6 @@ const (
|
||||
|
||||
type podCondition func(pod *v1.Pod) (bool, error)
|
||||
|
||||
type timeoutError struct {
|
||||
msg string
|
||||
observedObjects []interface{}
|
||||
}
|
||||
|
||||
func (e *timeoutError) Error() string {
|
||||
return e.msg
|
||||
}
|
||||
|
||||
func TimeoutError(msg string, observedObjects ...interface{}) *timeoutError {
|
||||
return &timeoutError{
|
||||
msg: msg,
|
||||
observedObjects: observedObjects,
|
||||
}
|
||||
}
|
||||
|
||||
// FinalError constructs an error that indicates to a poll function that
|
||||
// polling can be stopped immediately because some permanent error has been
|
||||
// encountered that is not going to go away.
|
||||
//
|
||||
// TODO (@pohly): move this into framework once the refactoring from
|
||||
// https://github.com/kubernetes/kubernetes/pull/112043 allows it. Right now it
|
||||
// leads to circular dependencies.
|
||||
func FinalError(err error) error {
|
||||
return &FinalErr{Err: err}
|
||||
}
|
||||
|
||||
type FinalErr struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (err *FinalErr) Error() string {
|
||||
if err.Err != nil {
|
||||
return fmt.Sprintf("final error: %s", err.Err.Error())
|
||||
}
|
||||
return "final error, exact problem unknown"
|
||||
}
|
||||
|
||||
func (err *FinalErr) Unwrap() error {
|
||||
return err.Err
|
||||
}
|
||||
|
||||
// IsFinal checks whether the error was marked as final by wrapping some error
|
||||
// with FinalError.
|
||||
func IsFinal(err error) bool {
|
||||
var finalErr *FinalErr
|
||||
return errors.As(err, &finalErr)
|
||||
}
|
||||
|
||||
// maybeTimeoutError returns a TimeoutError if err is a timeout. Otherwise, wrap err.
|
||||
// taskFormat and taskArgs should be the task being performed when the error occurred,
|
||||
// e.g. "waiting for pod to be running".
|
||||
func maybeTimeoutError(err error, taskFormat string, taskArgs ...interface{}) error {
|
||||
if IsTimeout(err) {
|
||||
return TimeoutError(fmt.Sprintf("timed out while "+taskFormat, taskArgs...))
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("error while %s: %w", fmt.Sprintf(taskFormat, taskArgs...), err)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func IsTimeout(err error) bool {
|
||||
if err == wait.ErrWaitTimeout {
|
||||
return true
|
||||
}
|
||||
if _, ok := err.(*timeoutError); ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// errorBadPodsStates create error message of basic info of bad pods for debugging.
|
||||
func errorBadPodsStates(badPods []v1.Pod, desiredPods int, ns, desiredState string, timeout time.Duration, err error) error {
|
||||
errStr := fmt.Sprintf("%d / %d pods in namespace %s are NOT in %s state in %v\n", len(badPods), desiredPods, ns, desiredState, timeout)
|
||||
|
||||
// Print bad pods info only if there are fewer than 10 bad pods
|
||||
if len(badPods) > 10 {
|
||||
errStr += "There are too many bad pods. Please check log for details."
|
||||
} else {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
w := tabwriter.NewWriter(buf, 0, 0, 1, ' ', 0)
|
||||
fmt.Fprintln(w, "POD\tNODE\tPHASE\tGRACE\tCONDITIONS")
|
||||
for _, badPod := range badPods {
|
||||
grace := ""
|
||||
if badPod.DeletionGracePeriodSeconds != nil {
|
||||
grace = fmt.Sprintf("%ds", *badPod.DeletionGracePeriodSeconds)
|
||||
}
|
||||
podInfo := fmt.Sprintf("%s\t%s\t%s\t%s\t%+v",
|
||||
badPod.ObjectMeta.Name, badPod.Spec.NodeName, badPod.Status.Phase, grace, badPod.Status.Conditions)
|
||||
fmt.Fprintln(w, podInfo)
|
||||
}
|
||||
w.Flush()
|
||||
errStr += buf.String()
|
||||
}
|
||||
|
||||
if err != nil && !IsTimeout(err) {
|
||||
return fmt.Errorf("%s\nLast error: %w", errStr, err)
|
||||
}
|
||||
return TimeoutError(errStr)
|
||||
}
|
||||
|
||||
// BeRunningNoRetries verifies that a pod starts running. It's a permanent
|
||||
// failure when the pod enters some other permanent phase.
|
||||
func BeRunningNoRetries() types.GomegaMatcher {
|
||||
@ -208,263 +108,265 @@ func BeInPhase(phase v1.PodPhase) types.GomegaMatcher {
|
||||
// example, in cluster startup, because the number of pods increases while
|
||||
// waiting. All pods that are in SUCCESS state are not counted.
|
||||
//
|
||||
// If ignoreLabels is not empty, pods matching this selector are ignored.
|
||||
//
|
||||
// If minPods or allowedNotReadyPods are -1, this method returns immediately
|
||||
// without waiting.
|
||||
func WaitForPodsRunningReady(ctx context.Context, c clientset.Interface, ns string, minPods, allowedNotReadyPods int32, timeout time.Duration, ignoreLabels map[string]string) error {
|
||||
func WaitForPodsRunningReady(ctx context.Context, c clientset.Interface, ns string, minPods, allowedNotReadyPods int32, timeout time.Duration) error {
|
||||
if minPods == -1 || allowedNotReadyPods == -1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ignoreSelector := labels.SelectorFromSet(map[string]string{})
|
||||
start := time.Now()
|
||||
framework.Logf("Waiting up to %v for all pods (need at least %d) in namespace '%s' to be running and ready",
|
||||
timeout, minPods, ns)
|
||||
var ignoreNotReady bool
|
||||
badPods := []v1.Pod{}
|
||||
desiredPods := 0
|
||||
notReady := int32(0)
|
||||
var lastAPIError error
|
||||
// We get the new list of pods, replication controllers, and replica
|
||||
// sets in every iteration because more pods come online during startup
|
||||
// and we want to ensure they are also checked.
|
||||
//
|
||||
// This struct gets populated while polling, then gets checked, and in
|
||||
// case of a timeout is included in the failure message.
|
||||
type state struct {
|
||||
ReplicationControllers []v1.ReplicationController
|
||||
ReplicaSets []appsv1.ReplicaSet
|
||||
Pods []v1.Pod
|
||||
}
|
||||
|
||||
if wait.PollImmediateWithContext(ctx, framework.PollInterval(), timeout, func(ctx context.Context) (bool, error) {
|
||||
// We get the new list of pods, replication controllers, and
|
||||
// replica sets in every iteration because more pods come
|
||||
// online during startup and we want to ensure they are also
|
||||
// checked.
|
||||
replicas, replicaOk := int32(0), int32(0)
|
||||
// Clear API error from the last attempt in case the following calls succeed.
|
||||
lastAPIError = nil
|
||||
// notReady is -1 for any failure other than a timeout.
|
||||
// Otherwise it is the number of pods that we were still
|
||||
// waiting for.
|
||||
notReady := int32(-1)
|
||||
|
||||
err := framework.Gomega().Eventually(ctx, framework.HandleRetry(func(ctx context.Context) (*state, error) {
|
||||
// Reset notReady at the start of a poll attempt.
|
||||
notReady = -1
|
||||
|
||||
rcList, err := c.CoreV1().ReplicationControllers(ns).List(ctx, metav1.ListOptions{})
|
||||
lastAPIError = err
|
||||
if err != nil {
|
||||
return handleWaitingAPIError(err, false, "listing replication controllers in namespace %s", ns)
|
||||
return nil, fmt.Errorf("listing replication controllers in namespace %s: %w", ns, err)
|
||||
}
|
||||
for _, rc := range rcList.Items {
|
||||
rsList, err := c.AppsV1().ReplicaSets(ns).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listing replication sets in namespace %s: %w", ns, err)
|
||||
}
|
||||
podList, err := c.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listing pods in namespace %s: %w", ns, err)
|
||||
}
|
||||
return &state{
|
||||
ReplicationControllers: rcList.Items,
|
||||
ReplicaSets: rsList.Items,
|
||||
Pods: podList.Items,
|
||||
}, nil
|
||||
})).WithTimeout(timeout).Should(framework.MakeMatcher(func(s *state) (func() string, error) {
|
||||
replicas, replicaOk := int32(0), int32(0)
|
||||
for _, rc := range s.ReplicationControllers {
|
||||
replicas += *rc.Spec.Replicas
|
||||
replicaOk += rc.Status.ReadyReplicas
|
||||
}
|
||||
|
||||
rsList, err := c.AppsV1().ReplicaSets(ns).List(ctx, metav1.ListOptions{})
|
||||
lastAPIError = err
|
||||
if err != nil {
|
||||
return handleWaitingAPIError(err, false, "listing replication sets in namespace %s", ns)
|
||||
}
|
||||
for _, rs := range rsList.Items {
|
||||
for _, rs := range s.ReplicaSets {
|
||||
replicas += *rs.Spec.Replicas
|
||||
replicaOk += rs.Status.ReadyReplicas
|
||||
}
|
||||
|
||||
podList, err := c.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{})
|
||||
lastAPIError = err
|
||||
if err != nil {
|
||||
return handleWaitingAPIError(err, false, "listing pods in namespace %s", ns)
|
||||
}
|
||||
nOk := int32(0)
|
||||
notReady = int32(0)
|
||||
badPods = []v1.Pod{}
|
||||
desiredPods = len(podList.Items)
|
||||
for _, pod := range podList.Items {
|
||||
if len(ignoreLabels) != 0 && ignoreSelector.Matches(labels.Set(pod.Labels)) {
|
||||
continue
|
||||
}
|
||||
failedPods := []v1.Pod{}
|
||||
otherPods := []v1.Pod{}
|
||||
succeededPods := []string{}
|
||||
for _, pod := range s.Pods {
|
||||
res, err := testutils.PodRunningReady(&pod)
|
||||
switch {
|
||||
case res && err == nil:
|
||||
nOk++
|
||||
case pod.Status.Phase == v1.PodSucceeded:
|
||||
framework.Logf("The status of Pod %s is Succeeded, skipping waiting", pod.ObjectMeta.Name)
|
||||
// it doesn't make sense to wait for this pod
|
||||
continue
|
||||
case pod.Status.Phase != v1.PodFailed:
|
||||
framework.Logf("The status of Pod %s is %s (Ready = false), waiting for it to be either Running (with Ready = true) or Failed", pod.ObjectMeta.Name, pod.Status.Phase)
|
||||
notReady++
|
||||
badPods = append(badPods, pod)
|
||||
default:
|
||||
if metav1.GetControllerOf(&pod) == nil {
|
||||
framework.Logf("Pod %s is Failed, but it's not controlled by a controller", pod.ObjectMeta.Name)
|
||||
badPods = append(badPods, pod)
|
||||
}
|
||||
succeededPods = append(succeededPods, pod.Name)
|
||||
case pod.Status.Phase == v1.PodFailed:
|
||||
// ignore failed pods that are controlled by some controller
|
||||
if metav1.GetControllerOf(&pod) == nil {
|
||||
failedPods = append(failedPods, pod)
|
||||
}
|
||||
default:
|
||||
notReady++
|
||||
otherPods = append(otherPods, pod)
|
||||
}
|
||||
}
|
||||
|
||||
framework.Logf("%d / %d pods in namespace '%s' are running and ready (%d seconds elapsed)",
|
||||
nOk, len(podList.Items), ns, int(time.Since(start).Seconds()))
|
||||
framework.Logf("expected %d pod replicas in namespace '%s', %d are Running and Ready.", replicas, ns, replicaOk)
|
||||
|
||||
if replicaOk == replicas && nOk >= minPods && len(badPods) == 0 {
|
||||
return true, nil
|
||||
}
|
||||
ignoreNotReady = (notReady <= allowedNotReadyPods)
|
||||
LogPodStates(badPods)
|
||||
return false, nil
|
||||
}) != nil {
|
||||
if !ignoreNotReady {
|
||||
return errorBadPodsStates(badPods, desiredPods, ns, "RUNNING and READY", timeout, lastAPIError)
|
||||
done := replicaOk == replicas && nOk >= minPods && (len(failedPods)+len(otherPods)) == 0
|
||||
if done {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Delayed formatting of a failure message.
|
||||
return func() string {
|
||||
var buffer strings.Builder
|
||||
buffer.WriteString(fmt.Sprintf("Expected all pods (need at least %d) in namespace %q to be running and ready (except for %d).\n", minPods, ns, allowedNotReadyPods))
|
||||
buffer.WriteString(fmt.Sprintf("%d / %d pods were running and ready.\n", nOk, len(s.Pods)))
|
||||
buffer.WriteString(fmt.Sprintf("Expected %d pod replicas, %d are Running and Ready.\n", replicas, replicaOk))
|
||||
if len(succeededPods) > 0 {
|
||||
buffer.WriteString(fmt.Sprintf("Pods that completed successfully:\n%s", format.Object(succeededPods, 1)))
|
||||
}
|
||||
if len(failedPods) > 0 {
|
||||
buffer.WriteString(fmt.Sprintf("Pods that failed and were not controlled by some controller:\n%s", format.Object(failedPods, 1)))
|
||||
}
|
||||
if len(otherPods) > 0 {
|
||||
buffer.WriteString(fmt.Sprintf("Pods that were neither completed nor running:\n%s", format.Object(otherPods, 1)))
|
||||
}
|
||||
return buffer.String()
|
||||
}, nil
|
||||
}))
|
||||
|
||||
// An error might not be fatal.
|
||||
if err != nil && notReady >= 0 && notReady <= allowedNotReadyPods {
|
||||
framework.Logf("Number of not-ready pods (%d) is below the allowed threshold (%d).", notReady, allowedNotReadyPods)
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// WaitForPodCondition waits a pods to be matched to the given condition.
|
||||
// If the condition callback returns an error that matches FinalErr (checked with IsFinal),
|
||||
// then polling aborts early.
|
||||
// The condition callback may use gomega.StopTrying to abort early.
|
||||
func WaitForPodCondition(ctx context.Context, c clientset.Interface, ns, podName, conditionDesc string, timeout time.Duration, condition podCondition) error {
|
||||
framework.Logf("Waiting up to %v for pod %q in namespace %q to be %q", timeout, podName, ns, conditionDesc)
|
||||
var (
|
||||
lastPodError error
|
||||
lastPod *v1.Pod
|
||||
start = time.Now()
|
||||
)
|
||||
err := wait.PollImmediateWithContext(ctx, framework.PollInterval(), timeout, func(ctx context.Context) (bool, error) {
|
||||
pod, err := c.CoreV1().Pods(ns).Get(ctx, podName, metav1.GetOptions{})
|
||||
lastPodError = err
|
||||
if err != nil {
|
||||
return handleWaitingAPIError(err, true, "getting pod %s", podIdentifier(ns, podName))
|
||||
}
|
||||
lastPod = pod // Don't overwrite if an error occurs after successfully retrieving.
|
||||
|
||||
// log now so that current pod info is reported before calling `condition()`
|
||||
framework.Logf("Pod %q: Phase=%q, Reason=%q, readiness=%t. Elapsed: %v",
|
||||
podName, pod.Status.Phase, pod.Status.Reason, podutils.IsPodReady(pod), time.Since(start))
|
||||
if done, err := condition(pod); done {
|
||||
if err == nil {
|
||||
framework.Logf("Pod %q satisfied condition %q", podName, conditionDesc)
|
||||
return framework.Gomega().
|
||||
Eventually(ctx, framework.RetryNotFound(framework.GetObject(c.CoreV1().Pods(ns).Get, podName, metav1.GetOptions{}))).
|
||||
WithTimeout(timeout).
|
||||
Should(framework.MakeMatcher(func(pod *v1.Pod) (func() string, error) {
|
||||
done, err := condition(pod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return true, err
|
||||
} else if err != nil {
|
||||
framework.Logf("Error evaluating pod condition %s: %v", conditionDesc, err)
|
||||
if IsFinal(err) {
|
||||
return false, err
|
||||
if done {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if IsTimeout(err) {
|
||||
if lastPod != nil {
|
||||
return TimeoutError(fmt.Sprintf("timed out while waiting for pod %s to be %s", podIdentifier(ns, podName), conditionDesc),
|
||||
lastPod,
|
||||
)
|
||||
} else if lastPodError != nil {
|
||||
// If the last API call was an error, propagate that instead of the timeout error.
|
||||
err = lastPodError
|
||||
}
|
||||
}
|
||||
return maybeTimeoutError(err, "waiting for pod %s to be %s", podIdentifier(ns, podName), conditionDesc)
|
||||
return func() string {
|
||||
return fmt.Sprintf("expected pod to be %s, got instead:\n%s", conditionDesc, format.Object(pod, 1))
|
||||
}, nil
|
||||
}))
|
||||
}
|
||||
|
||||
// WaitForAllPodsCondition waits for the listed pods to match the given condition.
|
||||
// To succeed, at least minPods must be listed, and all listed pods must match the condition.
|
||||
func WaitForAllPodsCondition(ctx context.Context, c clientset.Interface, ns string, opts metav1.ListOptions, minPods int, conditionDesc string, timeout time.Duration, condition podCondition) (*v1.PodList, error) {
|
||||
framework.Logf("Waiting up to %v for at least %d pods in namespace %s to be %s", timeout, minPods, ns, conditionDesc)
|
||||
var pods *v1.PodList
|
||||
matched := 0
|
||||
err := wait.PollImmediateWithContext(ctx, framework.PollInterval(), timeout, func(ctx context.Context) (done bool, err error) {
|
||||
pods, err = c.CoreV1().Pods(ns).List(ctx, opts)
|
||||
if err != nil {
|
||||
return handleWaitingAPIError(err, true, "listing pods")
|
||||
}
|
||||
// Range determines how many items must exist and how many must match a certain
|
||||
// condition. Values <= 0 are ignored.
|
||||
// TODO (?): move to test/e2e/framework/range
|
||||
type Range struct {
|
||||
// MinMatching must be <= actual matching items or <= 0.
|
||||
MinMatching int
|
||||
// MaxMatching must be >= actual matching items or <= 0.
|
||||
// To check for "no matching items", set NonMatching.
|
||||
MaxMatching int
|
||||
// NoneMatching indicates that no item must match.
|
||||
NoneMatching bool
|
||||
// AllMatching indicates that all items must match.
|
||||
AllMatching bool
|
||||
// MinFound must be <= existing items or <= 0.
|
||||
MinFound int
|
||||
}
|
||||
|
||||
// Min returns how many items must exist.
|
||||
func (r Range) Min() int {
|
||||
min := r.MinMatching
|
||||
if min < r.MinFound {
|
||||
min = r.MinFound
|
||||
}
|
||||
return min
|
||||
}
|
||||
|
||||
// WaitForPods waits for pods in the given namespace to match the given
|
||||
// condition. How many pods must exist and how many must match the condition
|
||||
// is determined by the range parameter. The condition callback may use
|
||||
// gomega.StopTrying(...).Now() to abort early. The condition description
|
||||
// will be used with "expected pods to <description>".
|
||||
func WaitForPods(ctx context.Context, c clientset.Interface, ns string, opts metav1.ListOptions, r Range, timeout time.Duration, conditionDesc string, condition func(*v1.Pod) bool) (*v1.PodList, error) {
|
||||
var finalPods *v1.PodList
|
||||
minPods := r.Min()
|
||||
match := func(pods *v1.PodList) (func() string, error) {
|
||||
finalPods = pods
|
||||
|
||||
if len(pods.Items) < minPods {
|
||||
framework.Logf("found %d pods, waiting for at least %d", len(pods.Items), minPods)
|
||||
return false, nil
|
||||
return func() string {
|
||||
return fmt.Sprintf("expected at least %d pods, only got %d", minPods, len(pods.Items))
|
||||
}, nil
|
||||
}
|
||||
|
||||
nonMatchingPods := []string{}
|
||||
var nonMatchingPods, matchingPods []v1.Pod
|
||||
for _, pod := range pods.Items {
|
||||
done, err := condition(&pod)
|
||||
if done && err != nil {
|
||||
return false, fmt.Errorf("error evaluating pod %s: %w", identifier(&pod), err)
|
||||
}
|
||||
if !done {
|
||||
nonMatchingPods = append(nonMatchingPods, identifier(&pod))
|
||||
if condition(&pod) {
|
||||
matchingPods = append(matchingPods, pod)
|
||||
} else {
|
||||
nonMatchingPods = append(nonMatchingPods, pod)
|
||||
}
|
||||
}
|
||||
matched = len(pods.Items) - len(nonMatchingPods)
|
||||
if len(nonMatchingPods) <= 0 {
|
||||
return true, nil // All pods match.
|
||||
matching := len(pods.Items) - len(nonMatchingPods)
|
||||
if matching < r.MinMatching && r.MinMatching > 0 {
|
||||
return func() string {
|
||||
return fmt.Sprintf("expected at least %d pods to %s, %d out of %d were not:\n%s",
|
||||
r.MinMatching, conditionDesc, len(nonMatchingPods), len(pods.Items),
|
||||
format.Object(nonMatchingPods, 1))
|
||||
}, nil
|
||||
}
|
||||
framework.Logf("%d pods are not %s: %v", len(nonMatchingPods), conditionDesc, nonMatchingPods)
|
||||
return false, nil
|
||||
})
|
||||
return pods, maybeTimeoutError(err, "waiting for at least %d pods to be %s (matched %d)", minPods, conditionDesc, matched)
|
||||
if len(nonMatchingPods) > 0 && r.AllMatching {
|
||||
return func() string {
|
||||
return fmt.Sprintf("expected all pods to %s, %d out of %d were not:\n%s",
|
||||
conditionDesc, len(nonMatchingPods), len(pods.Items),
|
||||
format.Object(nonMatchingPods, 1))
|
||||
}, nil
|
||||
}
|
||||
if matching > r.MaxMatching && r.MaxMatching > 0 {
|
||||
return func() string {
|
||||
return fmt.Sprintf("expected at most %d pods to %s, %d out of %d were:\n%s",
|
||||
r.MinMatching, conditionDesc, len(matchingPods), len(pods.Items),
|
||||
format.Object(matchingPods, 1))
|
||||
}, nil
|
||||
}
|
||||
if matching > 0 && r.NoneMatching {
|
||||
return func() string {
|
||||
return fmt.Sprintf("expected no pods to %s, %d out of %d were:\n%s",
|
||||
conditionDesc, len(matchingPods), len(pods.Items),
|
||||
format.Object(matchingPods, 1))
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
err := framework.Gomega().
|
||||
Eventually(ctx, framework.ListObjects(c.CoreV1().Pods(ns).List, opts)).
|
||||
WithTimeout(timeout).
|
||||
Should(framework.MakeMatcher(match))
|
||||
return finalPods, err
|
||||
}
|
||||
|
||||
// RunningReady checks whether pod p's phase is running and it has a ready
|
||||
// condition of status true.
|
||||
func RunningReady(p *v1.Pod) bool {
|
||||
return p.Status.Phase == v1.PodRunning && podutil.IsPodReady(p)
|
||||
}
|
||||
|
||||
// WaitForPodsRunning waits for a given `timeout` to evaluate if a certain amount of pods in given `ns` are running.
|
||||
func WaitForPodsRunning(c clientset.Interface, ns string, num int, timeout time.Duration) error {
|
||||
matched := 0
|
||||
err := wait.PollImmediate(framework.PollInterval(), timeout, func() (done bool, err error) {
|
||||
pods, err := c.CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return handleWaitingAPIError(err, true, "listing pods")
|
||||
}
|
||||
matched = 0
|
||||
for _, pod := range pods.Items {
|
||||
if ready, _ := testutils.PodRunningReady(&pod); ready {
|
||||
matched++
|
||||
}
|
||||
}
|
||||
if matched == num {
|
||||
return true, nil
|
||||
}
|
||||
framework.Logf("expect %d pods are running, but got %v", num, matched)
|
||||
return false, nil
|
||||
})
|
||||
return maybeTimeoutError(err, "waiting for pods to be running (want %v, matched %d)", num, matched)
|
||||
_, err := WaitForPods(context.TODO(), c, ns, metav1.ListOptions{}, Range{MinMatching: num, MaxMatching: num}, timeout,
|
||||
"be running and ready", func(pod *v1.Pod) bool {
|
||||
ready, _ := testutils.PodRunningReady(pod)
|
||||
return ready
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// WaitForPodsSchedulingGated waits for a given `timeout` to evaluate if a certain amount of pods in given `ns` stay in scheduling gated state.
|
||||
func WaitForPodsSchedulingGated(c clientset.Interface, ns string, num int, timeout time.Duration) error {
|
||||
matched := 0
|
||||
err := wait.PollImmediate(framework.PollInterval(), timeout, func() (done bool, err error) {
|
||||
pods, err := c.CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return handleWaitingAPIError(err, true, "listing pods")
|
||||
}
|
||||
matched = 0
|
||||
for _, pod := range pods.Items {
|
||||
_, err := WaitForPods(context.TODO(), c, ns, metav1.ListOptions{}, Range{MinMatching: num, MaxMatching: num}, timeout,
|
||||
"be in scheduling gated state", func(pod *v1.Pod) bool {
|
||||
for _, condition := range pod.Status.Conditions {
|
||||
if condition.Type == v1.PodScheduled && condition.Reason == v1.PodReasonSchedulingGated {
|
||||
matched++
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
if matched == num {
|
||||
return true, nil
|
||||
}
|
||||
framework.Logf("expect %d pods in scheduling gated state, but got %v", num, matched)
|
||||
return false, nil
|
||||
})
|
||||
return maybeTimeoutError(err, "waiting for pods to be scheduling gated (want %d, matched %d)", num, matched)
|
||||
return false
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// WaitForPodsWithSchedulingGates waits for a given `timeout` to evaluate if a certain amount of pods in given `ns`
|
||||
// match the given `schedulingGates`stay in scheduling gated state.
|
||||
func WaitForPodsWithSchedulingGates(c clientset.Interface, ns string, num int, timeout time.Duration, schedulingGates []v1.PodSchedulingGate) error {
|
||||
matched := 0
|
||||
err := wait.PollImmediate(framework.PollInterval(), timeout, func() (done bool, err error) {
|
||||
pods, err := c.CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return handleWaitingAPIError(err, true, "listing pods")
|
||||
}
|
||||
matched = 0
|
||||
for _, pod := range pods.Items {
|
||||
if reflect.DeepEqual(pod.Spec.SchedulingGates, schedulingGates) {
|
||||
matched++
|
||||
}
|
||||
}
|
||||
if matched == num {
|
||||
return true, nil
|
||||
}
|
||||
framework.Logf("expect %d pods carry the expected scheduling gates, but got %v", num, matched)
|
||||
return false, nil
|
||||
})
|
||||
return maybeTimeoutError(err, "waiting for pods to carry the expected scheduling gates (want %d, matched %d)", num, matched)
|
||||
_, err := WaitForPods(context.TODO(), c, ns, metav1.ListOptions{}, Range{MinMatching: num, MaxMatching: num}, timeout,
|
||||
"have certain scheduling gates", func(pod *v1.Pod) bool {
|
||||
return reflect.DeepEqual(pod.Spec.SchedulingGates, schedulingGates)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// WaitForPodTerminatedInNamespace returns an error if it takes too long for the pod to terminate,
|
||||
@ -550,18 +452,12 @@ func WaitForPodRunningInNamespaceSlow(ctx context.Context, c clientset.Interface
|
||||
}
|
||||
|
||||
// WaitTimeoutForPodRunningInNamespace waits the given timeout duration for the specified pod to become running.
|
||||
// It does not need to exist yet when this function gets called and the pod is not expected to be recreated
|
||||
// when it succeeds or fails.
|
||||
func WaitTimeoutForPodRunningInNamespace(ctx context.Context, c clientset.Interface, podName, namespace string, timeout time.Duration) error {
|
||||
return WaitForPodCondition(ctx, c, namespace, podName, "running", timeout, func(pod *v1.Pod) (bool, error) {
|
||||
switch pod.Status.Phase {
|
||||
case v1.PodRunning:
|
||||
return true, nil
|
||||
case v1.PodFailed:
|
||||
return false, errPodFailed
|
||||
case v1.PodSucceeded:
|
||||
return false, errPodCompleted
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
return framework.Gomega().Eventually(ctx, framework.RetryNotFound(framework.GetObject(c.CoreV1().Pods(namespace).Get, podName, metav1.GetOptions{}))).
|
||||
WithTimeout(timeout).
|
||||
Should(BeRunningNoRetries())
|
||||
}
|
||||
|
||||
// WaitForPodRunningInNamespace waits default amount of time (podStartTimeout) for the specified pod to become running.
|
||||
@ -595,17 +491,11 @@ func WaitForPodNoLongerRunningInNamespace(ctx context.Context, c clientset.Inter
|
||||
func WaitTimeoutForPodReadyInNamespace(ctx context.Context, c clientset.Interface, podName, namespace string, timeout time.Duration) error {
|
||||
return WaitForPodCondition(ctx, c, namespace, podName, "running and ready", timeout, func(pod *v1.Pod) (bool, error) {
|
||||
switch pod.Status.Phase {
|
||||
case v1.PodFailed:
|
||||
framework.Logf("The phase of Pod %s is %s which is unexpected, pod status: %#v", pod.Name, pod.Status.Phase, pod.Status)
|
||||
return false, errPodFailed
|
||||
case v1.PodSucceeded:
|
||||
framework.Logf("The phase of Pod %s is %s which is unexpected, pod status: %#v", pod.Name, pod.Status.Phase, pod.Status)
|
||||
return false, errPodCompleted
|
||||
case v1.PodFailed, v1.PodSucceeded:
|
||||
return false, gomega.StopTrying(fmt.Sprintf("The phase of Pod %s is %s which is unexpected.", pod.Name, pod.Status.Phase))
|
||||
case v1.PodRunning:
|
||||
framework.Logf("The phase of Pod %s is %s (Ready = %v)", pod.Name, pod.Status.Phase, podutils.IsPodReady(pod))
|
||||
return podutils.IsPodReady(pod), nil
|
||||
}
|
||||
framework.Logf("The phase of Pod %s is %s, waiting for it to be Running (with Ready = true)", pod.Name, pod.Status.Phase)
|
||||
return false, nil
|
||||
})
|
||||
}
|
||||
@ -637,108 +527,140 @@ func WaitForPodSuccessInNamespaceSlow(ctx context.Context, c clientset.Interface
|
||||
// WaitForPodNotFoundInNamespace returns an error if it takes too long for the pod to fully terminate.
|
||||
// Unlike `waitForPodTerminatedInNamespace`, the pod's Phase and Reason are ignored. If the pod Get
|
||||
// api returns IsNotFound then the wait stops and nil is returned. If the Get api returns an error other
|
||||
// than "not found" then that error is returned and the wait stops.
|
||||
// than "not found" and that error is final, that error is returned and the wait stops.
|
||||
func WaitForPodNotFoundInNamespace(ctx context.Context, c clientset.Interface, podName, ns string, timeout time.Duration) error {
|
||||
var lastPod *v1.Pod
|
||||
err := wait.PollImmediateWithContext(ctx, framework.PollInterval(), timeout, func(ctx context.Context) (bool, error) {
|
||||
err := framework.Gomega().Eventually(ctx, framework.HandleRetry(func(ctx context.Context) (*v1.Pod, error) {
|
||||
pod, err := c.CoreV1().Pods(ns).Get(ctx, podName, metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
return true, nil // done
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return handleWaitingAPIError(err, true, "getting pod %s", podIdentifier(ns, podName))
|
||||
}
|
||||
lastPod = pod
|
||||
return false, nil
|
||||
})
|
||||
if err == nil {
|
||||
return nil
|
||||
return pod, err
|
||||
})).WithTimeout(timeout).Should(gomega.BeNil())
|
||||
if err != nil {
|
||||
return fmt.Errorf("expected pod to not be found: %w", err)
|
||||
}
|
||||
if IsTimeout(err) && lastPod != nil {
|
||||
return TimeoutError(fmt.Sprintf("timed out while waiting for pod %s to be Not Found", podIdentifier(ns, podName)),
|
||||
lastPod,
|
||||
)
|
||||
}
|
||||
return maybeTimeoutError(err, "waiting for pod %s not found", podIdentifier(ns, podName))
|
||||
}
|
||||
|
||||
// WaitForPodToDisappear waits the given timeout duration for the specified pod to disappear.
|
||||
func WaitForPodToDisappear(ctx context.Context, c clientset.Interface, ns, podName string, label labels.Selector, interval, timeout time.Duration) error {
|
||||
var lastPod *v1.Pod
|
||||
err := wait.PollImmediateWithContext(ctx, interval, timeout, func(ctx context.Context) (bool, error) {
|
||||
framework.Logf("Waiting for pod %s to disappear", podName)
|
||||
options := metav1.ListOptions{LabelSelector: label.String()}
|
||||
pods, err := c.CoreV1().Pods(ns).List(ctx, options)
|
||||
if err != nil {
|
||||
return handleWaitingAPIError(err, true, "listing pods")
|
||||
}
|
||||
found := false
|
||||
for i, pod := range pods.Items {
|
||||
if pod.Name == podName {
|
||||
framework.Logf("Pod %s still exists", podName)
|
||||
found = true
|
||||
lastPod = &(pods.Items[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
framework.Logf("Pod %s no longer exists", podName)
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if IsTimeout(err) {
|
||||
return TimeoutError(fmt.Sprintf("timed out while waiting for pod %s to disappear", podIdentifier(ns, podName)),
|
||||
lastPod,
|
||||
)
|
||||
}
|
||||
return maybeTimeoutError(err, "waiting for pod %s to disappear", podIdentifier(ns, podName))
|
||||
return nil
|
||||
}
|
||||
|
||||
// PodsResponding waits for the pods to response.
|
||||
func PodsResponding(ctx context.Context, c clientset.Interface, ns, name string, wantName bool, pods *v1.PodList) error {
|
||||
func WaitForPodsResponding(ctx context.Context, c clientset.Interface, ns string, controllerName string, wantName bool, timeout time.Duration, pods *v1.PodList) error {
|
||||
if timeout == 0 {
|
||||
timeout = podRespondingTimeout
|
||||
}
|
||||
ginkgo.By("trying to dial each unique pod")
|
||||
label := labels.SelectorFromSet(labels.Set(map[string]string{"name": name}))
|
||||
err := wait.PollImmediateWithContext(ctx, framework.PollInterval(), podRespondingTimeout, NewProxyResponseChecker(c, ns, label, name, wantName, pods).CheckAllResponses)
|
||||
return maybeTimeoutError(err, "waiting for pods to be responsive")
|
||||
label := labels.SelectorFromSet(labels.Set(map[string]string{"name": controllerName}))
|
||||
options := metav1.ListOptions{LabelSelector: label.String()}
|
||||
|
||||
type response struct {
|
||||
podName string
|
||||
response string
|
||||
}
|
||||
|
||||
get := func(ctx context.Context) ([]response, error) {
|
||||
currentPods, err := c.CoreV1().Pods(ns).List(ctx, options)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list pods: %w", err)
|
||||
}
|
||||
|
||||
var responses []response
|
||||
for _, pod := range pods.Items {
|
||||
// Check that the replica list remains unchanged, otherwise we have problems.
|
||||
if !isElementOf(pod.UID, currentPods) {
|
||||
return nil, gomega.StopTrying(fmt.Sprintf("Pod with UID %s is no longer a member of the replica set. Must have been restarted for some reason.\nCurrent replica set:\n%s", pod.UID, format.Object(currentPods, 1)))
|
||||
}
|
||||
|
||||
ctxUntil, cancel := context.WithTimeout(ctx, singleCallTimeout)
|
||||
defer cancel()
|
||||
|
||||
body, err := c.CoreV1().RESTClient().Get().
|
||||
Namespace(ns).
|
||||
Resource("pods").
|
||||
SubResource("proxy").
|
||||
Name(string(pod.Name)).
|
||||
Do(ctxUntil).
|
||||
Raw()
|
||||
|
||||
if err != nil {
|
||||
// We may encounter errors here because of a race between the pod readiness and apiserver
|
||||
// proxy. So, we log the error and retry if this occurs.
|
||||
return nil, fmt.Errorf("Controller %s: failed to Get from replica pod %s:\n%s\nPod status:\n%s",
|
||||
controllerName, pod.Name,
|
||||
format.Object(err, 1), format.Object(pod.Status, 1))
|
||||
}
|
||||
responses = append(responses, response{podName: pod.Name, response: string(body)})
|
||||
}
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
match := func(responses []response) (func() string, error) {
|
||||
// The response checker expects the pod's name unless !respondName, in
|
||||
// which case it just checks for a non-empty response.
|
||||
var unexpected []response
|
||||
for _, response := range responses {
|
||||
if wantName {
|
||||
if response.response != response.podName {
|
||||
unexpected = append(unexpected, response)
|
||||
}
|
||||
} else {
|
||||
if len(response.response) == 0 {
|
||||
unexpected = append(unexpected, response)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(unexpected) > 0 {
|
||||
return func() string {
|
||||
what := "some response"
|
||||
if wantName {
|
||||
what = "the pod's own name as response"
|
||||
}
|
||||
return fmt.Sprintf("Wanted %s, but the following pods replied with something else:\n%s", what, format.Object(unexpected, 1))
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
err := framework.Gomega().
|
||||
Eventually(ctx, framework.HandleRetry(get)).
|
||||
WithTimeout(timeout).
|
||||
Should(framework.MakeMatcher(match))
|
||||
if err != nil {
|
||||
return fmt.Errorf("checking pod responses: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isElementOf(podUID apitypes.UID, pods *v1.PodList) bool {
|
||||
for _, pod := range pods.Items {
|
||||
if pod.UID == podUID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// WaitForNumberOfPods waits up to timeout to ensure there are exact
|
||||
// `num` pods in namespace `ns`.
|
||||
// It returns the matching Pods or a timeout error.
|
||||
func WaitForNumberOfPods(ctx context.Context, c clientset.Interface, ns string, num int, timeout time.Duration) (pods *v1.PodList, err error) {
|
||||
actualNum := 0
|
||||
err = wait.PollImmediateWithContext(ctx, framework.PollInterval(), timeout, func(ctx context.Context) (bool, error) {
|
||||
pods, err = c.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return handleWaitingAPIError(err, false, "listing pods")
|
||||
}
|
||||
actualNum = len(pods.Items)
|
||||
return actualNum == num, nil
|
||||
return WaitForPods(ctx, c, ns, metav1.ListOptions{}, Range{MinMatching: num, MaxMatching: num}, podScheduledBeforeTimeout, "exist", func(pod *v1.Pod) bool {
|
||||
return true
|
||||
})
|
||||
return pods, maybeTimeoutError(err, "waiting for there to be exactly %d pods in namespace (last seen %d)", num, actualNum)
|
||||
}
|
||||
|
||||
// WaitForPodsWithLabelScheduled waits for all matching pods to become scheduled and at least one
|
||||
// matching pod exists. Return the list of matching pods.
|
||||
func WaitForPodsWithLabelScheduled(ctx context.Context, c clientset.Interface, ns string, label labels.Selector) (pods *v1.PodList, err error) {
|
||||
opts := metav1.ListOptions{LabelSelector: label.String()}
|
||||
return WaitForAllPodsCondition(ctx, c, ns, opts, 1, "scheduled", podScheduledBeforeTimeout, func(pod *v1.Pod) (bool, error) {
|
||||
if pod.Spec.NodeName == "" {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
return WaitForPods(ctx, c, ns, opts, Range{MinFound: 1, AllMatching: true}, podScheduledBeforeTimeout, "be scheduled", func(pod *v1.Pod) bool {
|
||||
return pod.Spec.NodeName != ""
|
||||
})
|
||||
}
|
||||
|
||||
// WaitForPodsWithLabel waits up to podListTimeout for getting pods with certain label
|
||||
func WaitForPodsWithLabel(ctx context.Context, c clientset.Interface, ns string, label labels.Selector) (*v1.PodList, error) {
|
||||
opts := metav1.ListOptions{LabelSelector: label.String()}
|
||||
return WaitForAllPodsCondition(ctx, c, ns, opts, 1, "existent", podListTimeout, func(pod *v1.Pod) (bool, error) {
|
||||
return true, nil
|
||||
return WaitForPods(ctx, c, ns, opts, Range{MinFound: 1}, podListTimeout, "exist", func(pod *v1.Pod) bool {
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
@ -746,31 +668,39 @@ func WaitForPodsWithLabel(ctx context.Context, c clientset.Interface, ns string,
|
||||
// Return the list of matching pods.
|
||||
func WaitForPodsWithLabelRunningReady(ctx context.Context, c clientset.Interface, ns string, label labels.Selector, num int, timeout time.Duration) (pods *v1.PodList, err error) {
|
||||
opts := metav1.ListOptions{LabelSelector: label.String()}
|
||||
return WaitForAllPodsCondition(ctx, c, ns, opts, 1, "running and ready", timeout, testutils.PodRunningReady)
|
||||
return WaitForPods(ctx, c, ns, opts, Range{MinFound: num, AllMatching: true}, timeout, "be running and ready", RunningReady)
|
||||
}
|
||||
|
||||
// WaitForNRestartablePods tries to list restarting pods using ps until it finds expect of them,
|
||||
// returning their names if it can do so before timeout.
|
||||
func WaitForNRestartablePods(ctx context.Context, ps *testutils.PodStore, expect int, timeout time.Duration) ([]string, error) {
|
||||
var pods []*v1.Pod
|
||||
var errLast error
|
||||
found := wait.PollWithContext(ctx, framework.PollInterval(), timeout, func(ctx context.Context) (bool, error) {
|
||||
allPods := ps.List()
|
||||
|
||||
get := func(ctx context.Context) ([]*v1.Pod, error) {
|
||||
return ps.List(), nil
|
||||
}
|
||||
|
||||
match := func(allPods []*v1.Pod) (func() string, error) {
|
||||
pods = FilterNonRestartablePods(allPods)
|
||||
if len(pods) != expect {
|
||||
errLast = fmt.Errorf("expected to find %d pods but found only %d", expect, len(pods))
|
||||
framework.Logf("Error getting pods: %v", errLast)
|
||||
return false, nil
|
||||
return func() string {
|
||||
return fmt.Sprintf("expected to find non-restartable %d pods, but found %d:\n%s", expect, len(pods), format.Object(pods, 1))
|
||||
}, nil
|
||||
}
|
||||
return true, nil
|
||||
}) == nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
err := framework.Gomega().
|
||||
Eventually(ctx, framework.HandleRetry(get)).
|
||||
WithTimeout(timeout).
|
||||
Should(framework.MakeMatcher(match))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
podNames := make([]string, len(pods))
|
||||
for i, p := range pods {
|
||||
podNames[i] = p.ObjectMeta.Name
|
||||
}
|
||||
if !found {
|
||||
return podNames, fmt.Errorf("couldn't find %d pods within %v; last error: %v",
|
||||
expect, timeout, errLast)
|
||||
podNames[i] = p.Name
|
||||
}
|
||||
return podNames, nil
|
||||
}
|
||||
@ -842,23 +772,3 @@ func WaitForContainerRunning(ctx context.Context, c clientset.Interface, namespa
|
||||
return false, nil
|
||||
})
|
||||
}
|
||||
|
||||
// handleWaitingAPIErrror handles an error from an API request in the context of a Wait function.
|
||||
// If the error is retryable, sleep the recommended delay and ignore the error.
|
||||
// If the error is terminal, return it.
|
||||
func handleWaitingAPIError(err error, retryNotFound bool, taskFormat string, taskArgs ...interface{}) (bool, error) {
|
||||
taskDescription := fmt.Sprintf(taskFormat, taskArgs...)
|
||||
if retryNotFound && apierrors.IsNotFound(err) {
|
||||
framework.Logf("Ignoring NotFound error while " + taskDescription)
|
||||
return false, nil
|
||||
}
|
||||
if retry, delay := framework.ShouldRetry(err); retry {
|
||||
framework.Logf("Retryable error while %s, retrying after %v: %v", taskDescription, delay, err)
|
||||
if delay > 0 {
|
||||
time.Sleep(delay)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
framework.Logf("Encountered non-retryable error while %s: %v", taskDescription, err)
|
||||
return false, err
|
||||
}
|
||||
|
@ -18,19 +18,23 @@ package pod_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/v2"
|
||||
"github.com/onsi/ginkgo/v2/reporters"
|
||||
"github.com/onsi/gomega"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
"k8s.io/kubernetes/test/e2e/framework/internal/output"
|
||||
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
|
||||
_ "k8s.io/kubernetes/test/utils/format" // activate YAML object dumps
|
||||
)
|
||||
|
||||
// The line number of the following code is checked in TestFailureOutput below.
|
||||
@ -43,36 +47,67 @@ import (
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// This must be line #50.
|
||||
|
||||
var _ = ginkgo.Describe("pod", func() {
|
||||
ginkgo.It("not found", func(ctx context.Context) {
|
||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(ctx, clientSet, "no-such-pod", "default", timeout /* no explanation here to cover that code path */))
|
||||
ginkgo.It("not found, must exist", func(ctx context.Context) {
|
||||
gomega.Eventually(ctx, framework.HandleRetry(getNoSuchPod)).WithTimeout(timeout).Should(e2epod.BeInPhase(v1.PodRunning))
|
||||
})
|
||||
|
||||
ginkgo.It("not found, retry", func(ctx context.Context) {
|
||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(ctx, clientSet, "no-such-pod", "default", timeout))
|
||||
})
|
||||
|
||||
ginkgo.It("not found, retry with wrappers", func(ctx context.Context) {
|
||||
gomega.Eventually(ctx, framework.RetryNotFound(framework.HandleRetry(getNoSuchPod))).WithTimeout(timeout).Should(e2epod.BeInPhase(v1.PodRunning))
|
||||
})
|
||||
|
||||
ginkgo.It("not found, retry with inverted wrappers", func(ctx context.Context) {
|
||||
gomega.Eventually(ctx, framework.HandleRetry(framework.RetryNotFound(getNoSuchPod))).WithTimeout(timeout).Should(e2epod.BeInPhase(v1.PodRunning))
|
||||
})
|
||||
|
||||
ginkgo.It("not running", func(ctx context.Context) {
|
||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(ctx, clientSet, podName, podNamespace, timeout), "wait for pod %s running", podName /* tests printf formatting */)
|
||||
ginkgo.By(fmt.Sprintf("waiting for pod %s to run", podName))
|
||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(ctx, clientSet, podName, podNamespace, timeout))
|
||||
})
|
||||
|
||||
ginkgo.It("failed", func(ctx context.Context) {
|
||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(ctx, clientSet, failedPodName, podNamespace, timeout))
|
||||
})
|
||||
|
||||
ginkgo.It("gets reported with API error", func(ctx context.Context) {
|
||||
called := false
|
||||
getPod := func(ctx context.Context) (*v1.Pod, error) {
|
||||
if called {
|
||||
ginkgo.By("returning fake API error")
|
||||
return nil, apierrors.NewTooManyRequests("fake API error", 10)
|
||||
}
|
||||
called = true
|
||||
pod, err := clientSet.CoreV1().Pods(podNamespace).Get(ctx, podName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ginkgo.By("returning pod")
|
||||
return pod, err
|
||||
}
|
||||
gomega.Eventually(ctx, framework.HandleRetry(getPod)).WithTimeout(5 * timeout).Should(e2epod.BeInPhase(v1.PodRunning))
|
||||
})
|
||||
})
|
||||
|
||||
func getNoSuchPod(ctx context.Context) (*v1.Pod, error) {
|
||||
return clientSet.CoreV1().Pods("default").Get(ctx, "no-such-pod", metav1.GetOptions{})
|
||||
}
|
||||
|
||||
const (
|
||||
podName = "pending-pod"
|
||||
podNamespace = "default"
|
||||
failedPodName = "failed-pod"
|
||||
timeout = 5 * time.Second
|
||||
timeout = time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
clientSet = fake.NewSimpleClientset(
|
||||
&v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: podName, Namespace: podNamespace}},
|
||||
&v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: podName, Namespace: podNamespace}, Status: v1.PodStatus{Phase: v1.PodPending}},
|
||||
&v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: failedPodName, Namespace: podNamespace}, Status: v1.PodStatus{Phase: v1.PodFailed}},
|
||||
)
|
||||
)
|
||||
@ -80,35 +115,43 @@ var (
|
||||
func TestFailureOutput(t *testing.T) {
|
||||
|
||||
expected := output.TestResult{
|
||||
// "INFO: Ignoring ..." or "INFO: Pod ..." will normally occur
|
||||
// every two seconds, but we reduce it to one line because it
|
||||
// might occur less often on a loaded system.
|
||||
NormalizeOutput: func(output string) string {
|
||||
return trimDuplicateLines(output, "INFO: ")
|
||||
NormalizeOutput: func(in string) string {
|
||||
return regexp.MustCompile(`wait.go:[[:digit:]]*`).ReplaceAllString(in, `wait.go`)
|
||||
},
|
||||
Suite: reporters.JUnitTestSuite{
|
||||
Tests: 3,
|
||||
Failures: 3,
|
||||
Tests: 7,
|
||||
Failures: 7,
|
||||
Errors: 0,
|
||||
Disabled: 0,
|
||||
Skipped: 0,
|
||||
TestCases: []reporters.JUnitTestCase{
|
||||
{
|
||||
Name: "[It] pod not found",
|
||||
Name: "[It] pod not found, must exist",
|
||||
Status: "failed",
|
||||
Failure: &reporters.JUnitFailure{
|
||||
Type: "failed",
|
||||
Description: `[FAILED] error while waiting for pod default/no-such-pod to be running: pods "no-such-pod" not found
|
||||
Description: `[FAILED] Told to stop trying after <after>.
|
||||
Unexpected final error while getting *v1.Pod: pods "no-such-pod" not found
|
||||
In [It] at: wait_test.go:54 <time>
|
||||
`,
|
||||
},
|
||||
SystemErr: `> Enter [It] not found - wait_test.go:53 <time>
|
||||
INFO: Waiting up to 5s for pod "no-such-pod" in namespace "default" to be "running"
|
||||
INFO: Ignoring NotFound error while getting pod default/no-such-pod
|
||||
INFO: Unexpected error:
|
||||
<*fmt.wrapError>: {
|
||||
msg: "error while waiting for pod default/no-such-pod to be running: pods \"no-such-pod\" not found",
|
||||
err: <*errors.StatusError>{
|
||||
SystemErr: `> Enter [It] not found, must exist - wait_test.go:53 <time>
|
||||
[FAILED] Told to stop trying after <after>.
|
||||
Unexpected final error while getting *v1.Pod: pods "no-such-pod" not found
|
||||
In [It] at: wait_test.go:54 <time>
|
||||
< Exit [It] not found, must exist - wait_test.go:53 <time>
|
||||
`,
|
||||
},
|
||||
{
|
||||
Name: "[It] pod not found, retry",
|
||||
Status: "failed",
|
||||
Failure: &reporters.JUnitFailure{
|
||||
Type: "failed",
|
||||
Description: `[FAILED] Timed out after <after>.
|
||||
The function passed to Eventually returned the following error:
|
||||
pods "no-such-pod" not found
|
||||
<framework.transientError>: {
|
||||
error: <*errors.StatusError>{
|
||||
ErrStatus: {
|
||||
TypeMeta: {Kind: "", APIVersion: ""},
|
||||
ListMeta: {
|
||||
@ -125,134 +168,280 @@ INFO: Unexpected error:
|
||||
},
|
||||
},
|
||||
}
|
||||
[FAILED] error while waiting for pod default/no-such-pod to be running: pods "no-such-pod" not found
|
||||
In [It] at: wait_test.go:54 <time>
|
||||
< Exit [It] not found - wait_test.go:53 <time>
|
||||
In [It] at: wait_test.go:58 <time>
|
||||
`,
|
||||
},
|
||||
SystemErr: `> Enter [It] not found, retry - wait_test.go:57 <time>
|
||||
INFO: Failed inside E2E framework:
|
||||
k8s.io/kubernetes/test/e2e/framework/pod.WaitTimeoutForPodRunningInNamespace()
|
||||
wait.go
|
||||
k8s.io/kubernetes/test/e2e/framework/pod_test.glob..func1.2()
|
||||
wait_test.go:58
|
||||
[FAILED] Timed out after <after>.
|
||||
The function passed to Eventually returned the following error:
|
||||
pods "no-such-pod" not found
|
||||
<framework.transientError>: {
|
||||
error: <*errors.StatusError>{
|
||||
ErrStatus: {
|
||||
TypeMeta: {Kind: "", APIVersion: ""},
|
||||
ListMeta: {
|
||||
SelfLink: "",
|
||||
ResourceVersion: "",
|
||||
Continue: "",
|
||||
RemainingItemCount: nil,
|
||||
},
|
||||
Status: "Failure",
|
||||
Message: "pods \"no-such-pod\" not found",
|
||||
Reason: "NotFound",
|
||||
Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
|
||||
Code: 404,
|
||||
},
|
||||
},
|
||||
}
|
||||
In [It] at: wait_test.go:58 <time>
|
||||
< Exit [It] not found, retry - wait_test.go:57 <time>
|
||||
`,
|
||||
},
|
||||
{
|
||||
Name: "[It] pod not found, retry with wrappers",
|
||||
Status: "failed",
|
||||
Failure: &reporters.JUnitFailure{
|
||||
Type: "failed",
|
||||
Description: `[FAILED] Timed out after <after>.
|
||||
The function passed to Eventually returned the following error:
|
||||
pods "no-such-pod" not found
|
||||
<framework.transientError>: {
|
||||
error: <*errors.StatusError>{
|
||||
ErrStatus: {
|
||||
TypeMeta: {Kind: "", APIVersion: ""},
|
||||
ListMeta: {
|
||||
SelfLink: "",
|
||||
ResourceVersion: "",
|
||||
Continue: "",
|
||||
RemainingItemCount: nil,
|
||||
},
|
||||
Status: "Failure",
|
||||
Message: "pods \"no-such-pod\" not found",
|
||||
Reason: "NotFound",
|
||||
Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
|
||||
Code: 404,
|
||||
},
|
||||
},
|
||||
}
|
||||
In [It] at: wait_test.go:62 <time>
|
||||
`,
|
||||
},
|
||||
SystemErr: `> Enter [It] not found, retry with wrappers - wait_test.go:61 <time>
|
||||
[FAILED] Timed out after <after>.
|
||||
The function passed to Eventually returned the following error:
|
||||
pods "no-such-pod" not found
|
||||
<framework.transientError>: {
|
||||
error: <*errors.StatusError>{
|
||||
ErrStatus: {
|
||||
TypeMeta: {Kind: "", APIVersion: ""},
|
||||
ListMeta: {
|
||||
SelfLink: "",
|
||||
ResourceVersion: "",
|
||||
Continue: "",
|
||||
RemainingItemCount: nil,
|
||||
},
|
||||
Status: "Failure",
|
||||
Message: "pods \"no-such-pod\" not found",
|
||||
Reason: "NotFound",
|
||||
Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
|
||||
Code: 404,
|
||||
},
|
||||
},
|
||||
}
|
||||
In [It] at: wait_test.go:62 <time>
|
||||
< Exit [It] not found, retry with wrappers - wait_test.go:61 <time>
|
||||
`,
|
||||
},
|
||||
{
|
||||
Name: "[It] pod not found, retry with inverted wrappers",
|
||||
Status: "failed",
|
||||
Failure: &reporters.JUnitFailure{
|
||||
Type: "failed",
|
||||
Description: `[FAILED] Timed out after <after>.
|
||||
The function passed to Eventually returned the following error:
|
||||
pods "no-such-pod" not found
|
||||
<framework.transientError>: {
|
||||
error: <*errors.StatusError>{
|
||||
ErrStatus: {
|
||||
TypeMeta: {Kind: "", APIVersion: ""},
|
||||
ListMeta: {
|
||||
SelfLink: "",
|
||||
ResourceVersion: "",
|
||||
Continue: "",
|
||||
RemainingItemCount: nil,
|
||||
},
|
||||
Status: "Failure",
|
||||
Message: "pods \"no-such-pod\" not found",
|
||||
Reason: "NotFound",
|
||||
Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
|
||||
Code: 404,
|
||||
},
|
||||
},
|
||||
}
|
||||
In [It] at: wait_test.go:66 <time>
|
||||
`,
|
||||
},
|
||||
SystemErr: `> Enter [It] not found, retry with inverted wrappers - wait_test.go:65 <time>
|
||||
[FAILED] Timed out after <after>.
|
||||
The function passed to Eventually returned the following error:
|
||||
pods "no-such-pod" not found
|
||||
<framework.transientError>: {
|
||||
error: <*errors.StatusError>{
|
||||
ErrStatus: {
|
||||
TypeMeta: {Kind: "", APIVersion: ""},
|
||||
ListMeta: {
|
||||
SelfLink: "",
|
||||
ResourceVersion: "",
|
||||
Continue: "",
|
||||
RemainingItemCount: nil,
|
||||
},
|
||||
Status: "Failure",
|
||||
Message: "pods \"no-such-pod\" not found",
|
||||
Reason: "NotFound",
|
||||
Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
|
||||
Code: 404,
|
||||
},
|
||||
},
|
||||
}
|
||||
In [It] at: wait_test.go:66 <time>
|
||||
< Exit [It] not found, retry with inverted wrappers - wait_test.go:65 <time>
|
||||
`,
|
||||
},
|
||||
{
|
||||
Name: "[It] pod not running",
|
||||
Status: "failed",
|
||||
Failure: &reporters.JUnitFailure{
|
||||
Description: `[FAILED] wait for pod pending-pod running: timed out while waiting for pod default/pending-pod to be running
|
||||
In [It] at: wait_test.go:58 <time>
|
||||
Description: `[FAILED] Timed out after <after>.
|
||||
Expected Pod to be in <v1.PodPhase>: "Running"
|
||||
Got instead:
|
||||
<*v1.Pod>:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: pending-pod
|
||||
namespace: default
|
||||
spec:
|
||||
containers: null
|
||||
status:
|
||||
phase: Pending
|
||||
In [It] at: wait_test.go:71 <time>
|
||||
`,
|
||||
Type: "failed",
|
||||
},
|
||||
SystemErr: `> Enter [It] not running - wait_test.go:57 <time>
|
||||
INFO: Waiting up to 5s for pod "pending-pod" in namespace "default" to be "running"
|
||||
INFO: Pod "pending-pod": Phase="", Reason="", readiness=false. Elapsed: <elapsed>
|
||||
INFO: Unexpected error: wait for pod pending-pod running:
|
||||
<*pod.timeoutError>: {
|
||||
msg: "timed out while waiting for pod default/pending-pod to be running",
|
||||
observedObjects: [
|
||||
<*v1.Pod>{
|
||||
TypeMeta: {Kind: "", APIVersion: ""},
|
||||
ObjectMeta: {
|
||||
Name: "pending-pod",
|
||||
GenerateName: "",
|
||||
Namespace: "default",
|
||||
SelfLink: "",
|
||||
UID: "",
|
||||
ResourceVersion: "",
|
||||
Generation: 0,
|
||||
CreationTimestamp: {
|
||||
Time: {wall: 0, ext: 0, loc: nil},
|
||||
},
|
||||
DeletionTimestamp: nil,
|
||||
DeletionGracePeriodSeconds: nil,
|
||||
Labels: nil,
|
||||
Annotations: nil,
|
||||
OwnerReferences: nil,
|
||||
Finalizers: nil,
|
||||
ManagedFields: nil,
|
||||
},
|
||||
Spec: {
|
||||
Volumes: nil,
|
||||
InitContainers: nil,
|
||||
Containers: nil,
|
||||
EphemeralContainers: nil,
|
||||
RestartPolicy: "",
|
||||
TerminationGracePeriodSeconds: nil,
|
||||
ActiveDeadlineSeconds: nil,
|
||||
DNSPolicy: "",
|
||||
NodeSelector: nil,
|
||||
ServiceAccountName: "",
|
||||
DeprecatedServiceAccount: "",
|
||||
AutomountServiceAccountToken: nil,
|
||||
NodeName: "",
|
||||
HostNetwork: false,
|
||||
HostPID: false,
|
||||
HostIPC: false,
|
||||
ShareProcessNamespace: nil,
|
||||
SecurityContext: nil,
|
||||
ImagePullSecrets: nil,
|
||||
Hostname: "",
|
||||
Subdomain: "",
|
||||
Affinity: nil,
|
||||
SchedulerName: "",
|
||||
Tolerations: nil,
|
||||
HostAliases: nil,
|
||||
PriorityClassName: "",
|
||||
Priority: nil,
|
||||
DNSConfig: nil,
|
||||
ReadinessGates: nil,
|
||||
RuntimeClassName: nil,
|
||||
EnableServiceLinks: nil,
|
||||
PreemptionPolicy: nil,
|
||||
Overhead: nil,
|
||||
TopologySpreadConstraints: nil,
|
||||
SetHostnameAsFQDN: nil,
|
||||
OS: nil,
|
||||
HostUsers: nil,
|
||||
SchedulingGates: nil,
|
||||
ResourceClaims: nil,
|
||||
},
|
||||
Status: {
|
||||
Phase: "",
|
||||
Conditions: nil,
|
||||
Message: "",
|
||||
Reason: "",
|
||||
NominatedNodeName: "",
|
||||
HostIP: "",
|
||||
PodIP: "",
|
||||
PodIPs: nil,
|
||||
StartTime: nil,
|
||||
InitContainerStatuses: nil,
|
||||
ContainerStatuses: nil,
|
||||
QOSClass: "",
|
||||
EphemeralContainerStatuses: nil,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
[FAILED] wait for pod pending-pod running: timed out while waiting for pod default/pending-pod to be running
|
||||
In [It] at: wait_test.go:58 <time>
|
||||
< Exit [It] not running - wait_test.go:57 <time>
|
||||
SystemErr: `> Enter [It] not running - wait_test.go:69 <time>
|
||||
STEP: waiting for pod pending-pod to run - wait_test.go:70 <time>
|
||||
INFO: Failed inside E2E framework:
|
||||
k8s.io/kubernetes/test/e2e/framework/pod.WaitTimeoutForPodRunningInNamespace()
|
||||
wait.go
|
||||
k8s.io/kubernetes/test/e2e/framework/pod_test.glob..func1.5()
|
||||
wait_test.go:71
|
||||
[FAILED] Timed out after <after>.
|
||||
Expected Pod to be in <v1.PodPhase>: "Running"
|
||||
Got instead:
|
||||
<*v1.Pod>:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: pending-pod
|
||||
namespace: default
|
||||
spec:
|
||||
containers: null
|
||||
status:
|
||||
phase: Pending
|
||||
In [It] at: wait_test.go:71 <time>
|
||||
< Exit [It] not running - wait_test.go:69 <time>
|
||||
`,
|
||||
},
|
||||
{
|
||||
Name: "[It] pod failed",
|
||||
Status: "failed",
|
||||
Failure: &reporters.JUnitFailure{
|
||||
Description: `[FAILED] error while waiting for pod default/failed-pod to be running: final error: pod failed permanently
|
||||
In [It] at: wait_test.go:62 <time>
|
||||
Description: `[FAILED] Told to stop trying after <after>.
|
||||
Expected pod to reach phase "Running", got final phase "Failed" instead.
|
||||
In [It] at: wait_test.go:75 <time>
|
||||
`,
|
||||
Type: "failed",
|
||||
},
|
||||
SystemErr: `> Enter [It] failed - wait_test.go:61 <time>
|
||||
INFO: Waiting up to 5s for pod "failed-pod" in namespace "default" to be "running"
|
||||
<*fmt.wrapError>: {
|
||||
msg: "error while waiting for pod default/failed-pod to be running: final error: pod failed permanently",
|
||||
err: <*pod.FinalErr>{
|
||||
Err: <*errors.errorString>{
|
||||
s: "pod failed permanently",
|
||||
},
|
||||
},
|
||||
SystemErr: `> Enter [It] failed - wait_test.go:74 <time>
|
||||
INFO: Failed inside E2E framework:
|
||||
k8s.io/kubernetes/test/e2e/framework/pod.WaitTimeoutForPodRunningInNamespace()
|
||||
wait.go
|
||||
k8s.io/kubernetes/test/e2e/framework/pod_test.glob..func1.6()
|
||||
wait_test.go:75
|
||||
[FAILED] Told to stop trying after <after>.
|
||||
Expected pod to reach phase "Running", got final phase "Failed" instead.
|
||||
In [It] at: wait_test.go:75 <time>
|
||||
< Exit [It] failed - wait_test.go:74 <time>
|
||||
`,
|
||||
},
|
||||
{
|
||||
Name: "[It] pod gets reported with API error",
|
||||
Status: "failed",
|
||||
Failure: &reporters.JUnitFailure{
|
||||
Description: `[FAILED] Timed out after <after>.
|
||||
The function passed to Eventually returned the following error:
|
||||
fake API error
|
||||
<*errors.StatusError>: {
|
||||
ErrStatus:
|
||||
code: 429
|
||||
details:
|
||||
retryAfterSeconds: 10
|
||||
message: fake API error
|
||||
metadata: {}
|
||||
reason: TooManyRequests
|
||||
status: Failure,
|
||||
}
|
||||
[FAILED] error while waiting for pod default/failed-pod to be running: final error: pod failed permanently
|
||||
In [It] at: wait_test.go:62 <time>
|
||||
< Exit [It] failed - wait_test.go:61 <time>
|
||||
At one point, however, the function did return successfully.
|
||||
Yet, Eventually failed because the matcher was not satisfied:
|
||||
Expected Pod to be in <v1.PodPhase>: "Running"
|
||||
Got instead:
|
||||
<*v1.Pod>:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: pending-pod
|
||||
namespace: default
|
||||
spec:
|
||||
containers: null
|
||||
status:
|
||||
phase: Pending
|
||||
In [It] at: wait_test.go:93 <time>
|
||||
`,
|
||||
Type: "failed",
|
||||
},
|
||||
SystemErr: `> Enter [It] gets reported with API error - wait_test.go:78 <time>
|
||||
STEP: returning pod - wait_test.go:90 <time>
|
||||
STEP: returning fake API error - wait_test.go:82 <time>
|
||||
[FAILED] Timed out after <after>.
|
||||
The function passed to Eventually returned the following error:
|
||||
fake API error
|
||||
<*errors.StatusError>: {
|
||||
ErrStatus:
|
||||
code: 429
|
||||
details:
|
||||
retryAfterSeconds: 10
|
||||
message: fake API error
|
||||
metadata: {}
|
||||
reason: TooManyRequests
|
||||
status: Failure,
|
||||
}
|
||||
At one point, however, the function did return successfully.
|
||||
Yet, Eventually failed because the matcher was not satisfied:
|
||||
Expected Pod to be in <v1.PodPhase>: "Running"
|
||||
Got instead:
|
||||
<*v1.Pod>:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: pending-pod
|
||||
namespace: default
|
||||
spec:
|
||||
containers: null
|
||||
status:
|
||||
phase: Pending
|
||||
In [It] at: wait_test.go:93 <time>
|
||||
< Exit [It] gets reported with API error - wait_test.go:78 <time>
|
||||
`,
|
||||
},
|
||||
},
|
||||
@ -260,24 +449,3 @@ In [It] at: wait_test.go:62 <time>
|
||||
}
|
||||
output.TestGinkgoOutput(t, expected)
|
||||
}
|
||||
|
||||
func trimDuplicateLines(output, prefix string) string {
|
||||
lines := strings.Split(output, "\n")
|
||||
trimming := false
|
||||
validLines := 0
|
||||
for i := 0; i < len(lines); i++ {
|
||||
if strings.HasPrefix(lines[i], prefix) {
|
||||
// Keep the first line, and only that one.
|
||||
if !trimming {
|
||||
trimming = true
|
||||
lines[validLines] = lines[i]
|
||||
validLines++
|
||||
}
|
||||
} else {
|
||||
trimming = false
|
||||
lines[validLines] = lines[i]
|
||||
validLines++
|
||||
}
|
||||
}
|
||||
return strings.Join(lines[0:validLines], "\n")
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ func (p *Provider) GroupSize(group string) (int, error) {
|
||||
client := autoscaling.New(awsSession)
|
||||
instanceGroup, err := awscloud.DescribeInstanceGroup(client, group)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("error describing instance group: %v", err)
|
||||
return -1, fmt.Errorf("error describing instance group: %w", err)
|
||||
}
|
||||
if instanceGroup == nil {
|
||||
return -1, fmt.Errorf("instance group not found: %s", group)
|
||||
@ -157,7 +157,7 @@ func (p *Provider) DeletePD(pdName string) error {
|
||||
if awsError, ok := err.(awserr.Error); ok && awsError.Code() == "InvalidVolume.NotFound" {
|
||||
framework.Logf("volume deletion implicitly succeeded because volume %q does not exist.", pdName)
|
||||
} else {
|
||||
return fmt.Errorf("error deleting EBS volumes: %v", err)
|
||||
return fmt.Errorf("error deleting EBS volumes: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -374,22 +374,22 @@ func VerifyFirewallRule(res, exp *compute.Firewall, network string, portsSubset
|
||||
expPorts := PackProtocolsPortsFromFirewall(exp.Allowed)
|
||||
if portsSubset {
|
||||
if err := isPortsSubset(expPorts, actualPorts); err != nil {
|
||||
return fmt.Errorf("incorrect allowed protocol ports: %v", err)
|
||||
return fmt.Errorf("incorrect allowed protocol ports: %w", err)
|
||||
}
|
||||
} else {
|
||||
if err := SameStringArray(actualPorts, expPorts, false); err != nil {
|
||||
return fmt.Errorf("incorrect allowed protocols ports: %v", err)
|
||||
return fmt.Errorf("incorrect allowed protocols ports: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := SameStringArray(res.SourceRanges, exp.SourceRanges, false); err != nil {
|
||||
return fmt.Errorf("incorrect source ranges %v, expected %v: %v", res.SourceRanges, exp.SourceRanges, err)
|
||||
return fmt.Errorf("incorrect source ranges %v, expected %v: %w", res.SourceRanges, exp.SourceRanges, err)
|
||||
}
|
||||
if err := SameStringArray(res.SourceTags, exp.SourceTags, false); err != nil {
|
||||
return fmt.Errorf("incorrect source tags %v, expected %v: %v", res.SourceTags, exp.SourceTags, err)
|
||||
return fmt.Errorf("incorrect source tags %v, expected %v: %w", res.SourceTags, exp.SourceTags, err)
|
||||
}
|
||||
if err := SameStringArray(res.TargetTags, exp.TargetTags, false); err != nil {
|
||||
return fmt.Errorf("incorrect target tags %v, expected %v: %v", res.TargetTags, exp.TargetTags, err)
|
||||
return fmt.Errorf("incorrect target tags %v, expected %v: %w", res.TargetTags, exp.TargetTags, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ func factory() (framework.ProviderInterface, error) {
|
||||
if region == "" {
|
||||
region, err = gcecloud.GetGCERegion(zone)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing GCE/GKE region from zone %q: %v", zone, err)
|
||||
return nil, fmt.Errorf("error parsing GCE/GKE region from zone %q: %w", zone, err)
|
||||
}
|
||||
}
|
||||
managedZones := []string{} // Manage all zones in the region
|
||||
@ -95,7 +95,7 @@ func factory() (framework.ProviderInterface, error) {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error building GCE/GKE provider: %v", err)
|
||||
return nil, fmt.Errorf("Error building GCE/GKE provider: %w", err)
|
||||
}
|
||||
|
||||
// Arbitrarily pick one of the zones we have nodes in, looking at prepopulated zones first.
|
||||
@ -189,7 +189,7 @@ func (p *Provider) EnsureLoadBalancerResourcesDeleted(ctx context.Context, ip, p
|
||||
project := framework.TestContext.CloudConfig.ProjectID
|
||||
region, err := gcecloud.GetGCERegion(framework.TestContext.CloudConfig.Zone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get region for zone %q: %v", framework.TestContext.CloudConfig.Zone, err)
|
||||
return fmt.Errorf("could not get region for zone %q: %w", framework.TestContext.CloudConfig.Zone, err)
|
||||
}
|
||||
|
||||
return wait.PollWithContext(ctx, 10*time.Second, 5*time.Minute, func(ctx context.Context) (bool, error) {
|
||||
@ -304,7 +304,7 @@ func (p *Provider) cleanupGCEResources(ctx context.Context, c clientset.Interfac
|
||||
var err error
|
||||
region, err = gcecloud.GetGCERegion(zone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing GCE/GKE region from zone %q: %v", zone, err)
|
||||
return fmt.Errorf("error parsing GCE/GKE region from zone %q: %w", zone, err)
|
||||
}
|
||||
}
|
||||
if err := p.gceCloud.DeleteFirewall(gcecloud.MakeFirewallName(loadBalancerName)); err != nil &&
|
||||
@ -404,7 +404,7 @@ func GetGCECloud() (*gcecloud.Cloud, error) {
|
||||
func GetClusterID(ctx context.Context, c clientset.Interface) (string, error) {
|
||||
cm, err := c.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(ctx, gcecloud.UIDConfigMapName, metav1.GetOptions{})
|
||||
if err != nil || cm == nil {
|
||||
return "", fmt.Errorf("error getting cluster ID: %v", err)
|
||||
return "", fmt.Errorf("error getting cluster ID: %w", err)
|
||||
}
|
||||
clusterID, clusterIDExists := cm.Data[gcecloud.UIDCluster]
|
||||
providerID, providerIDExists := cm.Data[gcecloud.UIDProvider]
|
||||
|
@ -641,12 +641,12 @@ func (cont *IngressController) verifyBackendMode(svcPorts map[string]v1.ServiceP
|
||||
gceCloud := cont.Cloud.Provider.(*Provider).gceCloud
|
||||
beList, err := gceCloud.ListGlobalBackendServices()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list backend services: %v", err)
|
||||
return fmt.Errorf("failed to list backend services: %w", err)
|
||||
}
|
||||
|
||||
hcList, err := gceCloud.ListHealthChecks()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list health checks: %v", err)
|
||||
return fmt.Errorf("failed to list health checks: %w", err)
|
||||
}
|
||||
|
||||
// Generate short UID
|
||||
|
@ -141,7 +141,7 @@ func PVPVCCleanup(ctx context.Context, c clientset.Interface, ns string, pv *v1.
|
||||
if pvc != nil {
|
||||
err := DeletePersistentVolumeClaim(ctx, c, pvc.Name, ns)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to delete PVC %q: %v", pvc.Name, err))
|
||||
errs = append(errs, fmt.Errorf("failed to delete PVC %q: %w", pvc.Name, err))
|
||||
}
|
||||
} else {
|
||||
framework.Logf("pvc is nil")
|
||||
@ -149,7 +149,7 @@ func PVPVCCleanup(ctx context.Context, c clientset.Interface, ns string, pv *v1.
|
||||
if pv != nil {
|
||||
err := DeletePersistentVolume(ctx, c, pv.Name)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to delete PV %q: %v", pv.Name, err))
|
||||
errs = append(errs, fmt.Errorf("failed to delete PV %q: %w", pv.Name, err))
|
||||
}
|
||||
} else {
|
||||
framework.Logf("pv is nil")
|
||||
@ -166,7 +166,7 @@ func PVPVCMapCleanup(ctx context.Context, c clientset.Interface, ns string, pvol
|
||||
for pvcKey := range claims {
|
||||
err := DeletePersistentVolumeClaim(ctx, c, pvcKey.Name, ns)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to delete PVC %q: %v", pvcKey.Name, err))
|
||||
errs = append(errs, fmt.Errorf("failed to delete PVC %q: %w", pvcKey.Name, err))
|
||||
} else {
|
||||
delete(claims, pvcKey)
|
||||
}
|
||||
@ -175,7 +175,7 @@ func PVPVCMapCleanup(ctx context.Context, c clientset.Interface, ns string, pvol
|
||||
for pvKey := range pvols {
|
||||
err := DeletePersistentVolume(ctx, c, pvKey)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to delete PV %q: %v", pvKey, err))
|
||||
errs = append(errs, fmt.Errorf("failed to delete PV %q: %w", pvKey, err))
|
||||
} else {
|
||||
delete(pvols, pvKey)
|
||||
}
|
||||
@ -189,7 +189,7 @@ func DeletePersistentVolume(ctx context.Context, c clientset.Interface, pvName s
|
||||
framework.Logf("Deleting PersistentVolume %q", pvName)
|
||||
err := c.CoreV1().PersistentVolumes().Delete(ctx, pvName, metav1.DeleteOptions{})
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
return fmt.Errorf("PV Delete API error: %v", err)
|
||||
return fmt.Errorf("PV Delete API error: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -201,7 +201,7 @@ func DeletePersistentVolumeClaim(ctx context.Context, c clientset.Interface, pvc
|
||||
framework.Logf("Deleting PersistentVolumeClaim %q", pvcName)
|
||||
err := c.CoreV1().PersistentVolumeClaims(ns).Delete(ctx, pvcName, metav1.DeleteOptions{})
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
return fmt.Errorf("PVC Delete API error: %v", err)
|
||||
return fmt.Errorf("PVC Delete API error: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -222,13 +222,13 @@ func DeletePVCandValidatePV(ctx context.Context, c clientset.Interface, timeouts
|
||||
framework.Logf("Waiting for reclaim process to complete.")
|
||||
err = WaitForPersistentVolumePhase(ctx, expectPVPhase, c, pv.Name, framework.Poll, timeouts.PVReclaim)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pv %q phase did not become %v: %v", pv.Name, expectPVPhase, err)
|
||||
return fmt.Errorf("pv %q phase did not become %v: %w", pv.Name, expectPVPhase, err)
|
||||
}
|
||||
|
||||
// examine the pv's ClaimRef and UID and compare to expected values
|
||||
pv, err = c.CoreV1().PersistentVolumes().Get(ctx, pv.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("PV Get API error: %v", err)
|
||||
return fmt.Errorf("PV Get API error: %w", err)
|
||||
}
|
||||
cr := pv.Spec.ClaimRef
|
||||
if expectPVPhase == v1.VolumeAvailable {
|
||||
@ -260,7 +260,7 @@ func DeletePVCandValidatePVGroup(ctx context.Context, c clientset.Interface, tim
|
||||
for pvName := range pvols {
|
||||
pv, err := c.CoreV1().PersistentVolumes().Get(ctx, pvName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("PV Get API error: %v", err)
|
||||
return fmt.Errorf("PV Get API error: %w", err)
|
||||
}
|
||||
cr := pv.Spec.ClaimRef
|
||||
// if pv is bound then delete the pvc it is bound to
|
||||
@ -279,7 +279,7 @@ func DeletePVCandValidatePVGroup(ctx context.Context, c clientset.Interface, tim
|
||||
return err
|
||||
}
|
||||
} else if !apierrors.IsNotFound(err) {
|
||||
return fmt.Errorf("PVC Get API error: %v", err)
|
||||
return fmt.Errorf("PVC Get API error: %w", err)
|
||||
}
|
||||
// delete pvckey from map even if apierrors.IsNotFound above is true and thus the
|
||||
// claim was not actually deleted here
|
||||
@ -316,10 +316,10 @@ func createPV(ctx context.Context, c clientset.Interface, timeouts *framework.Ti
|
||||
})
|
||||
// if we have an error from creating the PV, use that instead of a timeout error
|
||||
if lastCreateErr != nil {
|
||||
return nil, fmt.Errorf("PV Create API error: %v", err)
|
||||
return nil, fmt.Errorf("PV Create API error: %w", err)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("PV Create API error: %v", err)
|
||||
return nil, fmt.Errorf("PV Create API error: %w", err)
|
||||
}
|
||||
|
||||
return resultPV, nil
|
||||
@ -334,7 +334,7 @@ func CreatePV(ctx context.Context, c clientset.Interface, timeouts *framework.Ti
|
||||
func CreatePVC(ctx context.Context, c clientset.Interface, ns string, pvc *v1.PersistentVolumeClaim) (*v1.PersistentVolumeClaim, error) {
|
||||
pvc, err := c.CoreV1().PersistentVolumeClaims(ns).Create(ctx, pvc, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("PVC Create API error: %v", err)
|
||||
return nil, fmt.Errorf("PVC Create API error: %w", err)
|
||||
}
|
||||
return pvc, nil
|
||||
}
|
||||
@ -464,24 +464,24 @@ func WaitOnPVandPVC(ctx context.Context, c clientset.Interface, timeouts *framew
|
||||
framework.Logf("Waiting for PV %v to bind to PVC %v", pv.Name, pvc.Name)
|
||||
err := WaitForPersistentVolumeClaimPhase(ctx, v1.ClaimBound, c, ns, pvc.Name, framework.Poll, timeouts.ClaimBound)
|
||||
if err != nil {
|
||||
return fmt.Errorf("PVC %q did not become Bound: %v", pvc.Name, err)
|
||||
return fmt.Errorf("PVC %q did not become Bound: %w", pvc.Name, err)
|
||||
}
|
||||
|
||||
// Wait for PersistentVolume.Status.Phase to be Bound, which it should be
|
||||
// since the PVC is already bound.
|
||||
err = WaitForPersistentVolumePhase(ctx, v1.VolumeBound, c, pv.Name, framework.Poll, timeouts.PVBound)
|
||||
if err != nil {
|
||||
return fmt.Errorf("PV %q did not become Bound: %v", pv.Name, err)
|
||||
return fmt.Errorf("PV %q did not become Bound: %w", pv.Name, err)
|
||||
}
|
||||
|
||||
// Re-get the pv and pvc objects
|
||||
pv, err = c.CoreV1().PersistentVolumes().Get(ctx, pv.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("PV Get API error: %v", err)
|
||||
return fmt.Errorf("PV Get API error: %w", err)
|
||||
}
|
||||
pvc, err = c.CoreV1().PersistentVolumeClaims(ns).Get(ctx, pvc.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("PVC Get API error: %v", err)
|
||||
return fmt.Errorf("PVC Get API error: %w", err)
|
||||
}
|
||||
|
||||
// The pv and pvc are both bound, but to each other?
|
||||
@ -523,12 +523,12 @@ func WaitAndVerifyBinds(ctx context.Context, c clientset.Interface, timeouts *fr
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("PV %q did not become Bound: %v", pvName, err)
|
||||
return fmt.Errorf("PV %q did not become Bound: %w", pvName, err)
|
||||
}
|
||||
|
||||
pv, err := c.CoreV1().PersistentVolumes().Get(ctx, pvName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("PV Get API error: %v", err)
|
||||
return fmt.Errorf("PV Get API error: %w", err)
|
||||
}
|
||||
cr := pv.Spec.ClaimRef
|
||||
if cr != nil && len(cr.Name) > 0 {
|
||||
@ -541,7 +541,7 @@ func WaitAndVerifyBinds(ctx context.Context, c clientset.Interface, timeouts *fr
|
||||
|
||||
err := WaitForPersistentVolumeClaimPhase(ctx, v1.ClaimBound, c, ns, cr.Name, framework.Poll, timeouts.ClaimBound)
|
||||
if err != nil {
|
||||
return fmt.Errorf("PVC %q did not become Bound: %v", cr.Name, err)
|
||||
return fmt.Errorf("PVC %q did not become Bound: %w", cr.Name, err)
|
||||
}
|
||||
actualBinds++
|
||||
}
|
||||
@ -665,7 +665,7 @@ func createPDWithRetry(ctx context.Context, zone string) (string, error) {
|
||||
for start := time.Now(); ; time.Sleep(pdRetryPollTime) {
|
||||
if time.Since(start) >= pdRetryTimeout ||
|
||||
ctx.Err() != nil {
|
||||
return "", fmt.Errorf("timed out while trying to create PD in zone %q, last error: %v", zone, err)
|
||||
return "", fmt.Errorf("timed out while trying to create PD in zone %q, last error: %w", zone, err)
|
||||
}
|
||||
|
||||
newDiskName, err = createPD(zone)
|
||||
@ -702,7 +702,7 @@ func DeletePDWithRetry(ctx context.Context, diskName string) error {
|
||||
for start := time.Now(); ; time.Sleep(pdRetryPollTime) {
|
||||
if time.Since(start) >= pdRetryTimeout ||
|
||||
ctx.Err() != nil {
|
||||
return fmt.Errorf("timed out while trying to delete PD %q, last error: %v", diskName, err)
|
||||
return fmt.Errorf("timed out while trying to delete PD %q, last error: %w", diskName, err)
|
||||
}
|
||||
err = deletePD(diskName)
|
||||
if err != nil {
|
||||
@ -737,12 +737,12 @@ func WaitForPVClaimBoundPhase(ctx context.Context, client clientset.Interface, p
|
||||
// Get new copy of the claim
|
||||
claim, err = client.CoreV1().PersistentVolumeClaims(claim.Namespace).Get(ctx, claim.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return persistentvolumes, fmt.Errorf("PVC Get API error: %v", err)
|
||||
return persistentvolumes, fmt.Errorf("PVC Get API error: %w", err)
|
||||
}
|
||||
// Get the bounded PV
|
||||
persistentvolumes[index], err = client.CoreV1().PersistentVolumes().Get(ctx, claim.Spec.VolumeName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return persistentvolumes, fmt.Errorf("PV Get API error: %v", err)
|
||||
return persistentvolumes, fmt.Errorf("PV Get API error: %w", err)
|
||||
}
|
||||
}
|
||||
return persistentvolumes, nil
|
||||
@ -822,7 +822,7 @@ func DeletePVSource(ctx context.Context, pvSource *v1.PersistentVolumeSource) er
|
||||
func GetDefaultStorageClassName(ctx context.Context, c clientset.Interface) (string, error) {
|
||||
list, err := c.StorageV1().StorageClasses().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error listing storage classes: %v", err)
|
||||
return "", fmt.Errorf("Error listing storage classes: %w", err)
|
||||
}
|
||||
var scName string
|
||||
for _, sc := range list.Items {
|
||||
|
@ -57,7 +57,7 @@ func ScaleResource(
|
||||
) error {
|
||||
ginkgo.By(fmt.Sprintf("Scaling %v %s in namespace %s to %d", kind, name, ns, size))
|
||||
if err := testutils.ScaleResourceWithRetries(scalesGetter, ns, name, size, gvr); err != nil {
|
||||
return fmt.Errorf("error while scaling RC %s to %d replicas: %v", name, size, err)
|
||||
return fmt.Errorf("error while scaling RC %s to %d replicas: %w", name, size, err)
|
||||
}
|
||||
if !wait {
|
||||
return nil
|
||||
@ -131,7 +131,7 @@ func deleteObjectAndWaitForGC(ctx context.Context, c clientset.Interface, rtObje
|
||||
if err == nil || apierrors.IsNotFound(err) {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("failed to delete object with non-retriable error: %v", err)
|
||||
return false, fmt.Errorf("failed to delete object with non-retriable error: %w", err)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -157,7 +157,7 @@ func deleteObjectAndWaitForGC(ctx context.Context, c clientset.Interface, rtObje
|
||||
|
||||
err = waitForPodsInactive(ctx, ps, interval, timeout)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while waiting for pods to become inactive %s: %v", name, err)
|
||||
return fmt.Errorf("error while waiting for pods to become inactive %s: %w", name, err)
|
||||
}
|
||||
terminatePodTime := time.Since(startTime) - deleteTime
|
||||
framework.Logf("Terminating %v %s pods took: %v", description, name, terminatePodTime)
|
||||
@ -167,7 +167,7 @@ func deleteObjectAndWaitForGC(ctx context.Context, c clientset.Interface, rtObje
|
||||
// restart VM in that case and delete the pod.
|
||||
err = waitForPodsGone(ctx, ps, interval, 20*time.Minute)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while waiting for pods gone %s: %v", name, err)
|
||||
return fmt.Errorf("error while waiting for pods gone %s: %w", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -231,7 +231,7 @@ func WaitForControlledPodsRunning(ctx context.Context, c clientset.Interface, ns
|
||||
}
|
||||
err = testutils.WaitForEnoughPodsWithLabelRunning(c, ns, selector, int(replicas))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error while waiting for replication controller %s pods to be running: %v", name, err)
|
||||
return fmt.Errorf("Error while waiting for replication controller %s pods to be running: %w", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ func GetSelectorFromRuntimeObject(obj runtime.Object) (labels.Selector, error) {
|
||||
case *autoscalingv1.Scale:
|
||||
selector, err := metav1.ParseToLabelSelector(typed.Status.Selector)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Parsing selector for: %v encountered an error: %v", obj, err)
|
||||
return nil, fmt.Errorf("Parsing selector for: %v encountered an error: %w", obj, err)
|
||||
}
|
||||
return metav1.LabelSelectorAsSelector(selector)
|
||||
default:
|
||||
|
@ -115,7 +115,7 @@ func (j *TestJig) CreateTCPServiceWithPort(ctx context.Context, tweak func(svc *
|
||||
}
|
||||
result, err := j.Client.CoreV1().Services(j.Namespace).Create(ctx, svc, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create TCP Service %q: %v", svc.Name, err)
|
||||
return nil, fmt.Errorf("failed to create TCP Service %q: %w", svc.Name, err)
|
||||
}
|
||||
return j.sanityCheckService(result, svc.Spec.Type)
|
||||
}
|
||||
@ -137,7 +137,7 @@ func (j *TestJig) CreateUDPService(ctx context.Context, tweak func(svc *v1.Servi
|
||||
}
|
||||
result, err := j.Client.CoreV1().Services(j.Namespace).Create(ctx, svc, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create UDP Service %q: %v", svc.Name, err)
|
||||
return nil, fmt.Errorf("failed to create UDP Service %q: %w", svc.Name, err)
|
||||
}
|
||||
return j.sanityCheckService(result, svc.Spec.Type)
|
||||
}
|
||||
@ -162,7 +162,7 @@ func (j *TestJig) CreateExternalNameService(ctx context.Context, tweak func(svc
|
||||
}
|
||||
result, err := j.Client.CoreV1().Services(j.Namespace).Create(ctx, svc, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create ExternalName Service %q: %v", svc.Name, err)
|
||||
return nil, fmt.Errorf("failed to create ExternalName Service %q: %w", svc.Name, err)
|
||||
}
|
||||
return j.sanityCheckService(result, svc.Spec.Type)
|
||||
}
|
||||
@ -254,7 +254,7 @@ func (j *TestJig) CreateLoadBalancerService(ctx context.Context, timeout time.Du
|
||||
}
|
||||
_, err := j.Client.CoreV1().Services(j.Namespace).Create(ctx, svc, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create LoadBalancer Service %q: %v", svc.Name, err)
|
||||
return nil, fmt.Errorf("failed to create LoadBalancer Service %q: %w", svc.Name, err)
|
||||
}
|
||||
|
||||
ginkgo.By("waiting for loadbalancer for service " + j.Namespace + "/" + j.Name)
|
||||
@ -521,7 +521,7 @@ func (j *TestJig) UpdateService(ctx context.Context, update func(*v1.Service)) (
|
||||
for i := 0; i < 3; i++ {
|
||||
service, err := j.Client.CoreV1().Services(j.Namespace).Get(ctx, j.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get Service %q: %v", j.Name, err)
|
||||
return nil, fmt.Errorf("failed to get Service %q: %w", j.Name, err)
|
||||
}
|
||||
update(service)
|
||||
result, err := j.Client.CoreV1().Services(j.Namespace).Update(ctx, service, metav1.UpdateOptions{})
|
||||
@ -529,7 +529,7 @@ func (j *TestJig) UpdateService(ctx context.Context, update func(*v1.Service)) (
|
||||
return j.sanityCheckService(result, service.Spec.Type)
|
||||
}
|
||||
if !apierrors.IsConflict(err) && !apierrors.IsServerTimeout(err) {
|
||||
return nil, fmt.Errorf("failed to update Service %q: %v", j.Name, err)
|
||||
return nil, fmt.Errorf("failed to update Service %q: %w", j.Name, err)
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("too many retries updating Service %q", j.Name)
|
||||
@ -706,7 +706,7 @@ func (j *TestJig) CreatePDB(ctx context.Context, rc *v1.ReplicationController) (
|
||||
return nil, fmt.Errorf("failed to create PDB %q %v", pdb.Name, err)
|
||||
}
|
||||
if err := j.waitForPdbReady(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed waiting for PDB to be ready: %v", err)
|
||||
return nil, fmt.Errorf("failed waiting for PDB to be ready: %w", err)
|
||||
}
|
||||
|
||||
return newPdb, nil
|
||||
@ -743,14 +743,14 @@ func (j *TestJig) Run(ctx context.Context, tweak func(rc *v1.ReplicationControll
|
||||
}
|
||||
result, err := j.Client.CoreV1().ReplicationControllers(j.Namespace).Create(ctx, rc, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create RC %q: %v", rc.Name, err)
|
||||
return nil, fmt.Errorf("failed to create RC %q: %w", rc.Name, err)
|
||||
}
|
||||
pods, err := j.waitForPodsCreated(ctx, int(*(rc.Spec.Replicas)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create pods: %v", err)
|
||||
return nil, fmt.Errorf("failed to create pods: %w", err)
|
||||
}
|
||||
if err := j.waitForPodsReady(ctx, pods); err != nil {
|
||||
return nil, fmt.Errorf("failed waiting for pods to be running: %v", err)
|
||||
return nil, fmt.Errorf("failed waiting for pods to be running: %w", err)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@ -760,21 +760,21 @@ func (j *TestJig) Scale(ctx context.Context, replicas int) error {
|
||||
rc := j.Name
|
||||
scale, err := j.Client.CoreV1().ReplicationControllers(j.Namespace).GetScale(ctx, rc, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get scale for RC %q: %v", rc, err)
|
||||
return fmt.Errorf("failed to get scale for RC %q: %w", rc, err)
|
||||
}
|
||||
|
||||
scale.ResourceVersion = "" // indicate the scale update should be unconditional
|
||||
scale.Spec.Replicas = int32(replicas)
|
||||
_, err = j.Client.CoreV1().ReplicationControllers(j.Namespace).UpdateScale(ctx, rc, scale, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to scale RC %q: %v", rc, err)
|
||||
return fmt.Errorf("failed to scale RC %q: %w", rc, err)
|
||||
}
|
||||
pods, err := j.waitForPodsCreated(ctx, replicas)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed waiting for pods: %v", err)
|
||||
return fmt.Errorf("failed waiting for pods: %w", err)
|
||||
}
|
||||
if err := j.waitForPodsReady(ctx, pods); err != nil {
|
||||
return fmt.Errorf("failed waiting for pods to be running: %v", err)
|
||||
return fmt.Errorf("failed waiting for pods to be running: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -1063,7 +1063,7 @@ func (j *TestJig) CreateSCTPServiceWithPort(ctx context.Context, tweak func(svc
|
||||
}
|
||||
result, err := j.Client.CoreV1().Services(j.Namespace).Create(ctx, svc, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create SCTP Service %q: %v", svc.Name, err)
|
||||
return nil, fmt.Errorf("failed to create SCTP Service %q: %w", svc.Name, err)
|
||||
}
|
||||
return j.sanityCheckService(result, svc.Spec.Type)
|
||||
}
|
||||
@ -1081,7 +1081,7 @@ func (j *TestJig) CreateLoadBalancerServiceWaitForClusterIPOnly(tweak func(svc *
|
||||
}
|
||||
result, err := j.Client.CoreV1().Services(j.Namespace).Create(context.TODO(), svc, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create LoadBalancer Service %q: %v", svc.Name, err)
|
||||
return nil, fmt.Errorf("failed to create LoadBalancer Service %q: %w", svc.Name, err)
|
||||
}
|
||||
|
||||
return j.sanityCheckService(result, v1.ServiceTypeLoadBalancer)
|
||||
|
@ -213,11 +213,11 @@ func SkipUnlessSSHKeyPresent() {
|
||||
func serverVersionGTE(v *utilversion.Version, c discovery.ServerVersionInterface) (bool, error) {
|
||||
serverVersion, err := c.ServerVersion()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Unable to get server version: %v", err)
|
||||
return false, fmt.Errorf("Unable to get server version: %w", err)
|
||||
}
|
||||
sv, err := utilversion.ParseSemantic(serverVersion.GitVersion)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Unable to parse server version %q: %v", serverVersion.GitVersion, err)
|
||||
return false, fmt.Errorf("Unable to parse server version %q: %w", serverVersion.GitVersion, err)
|
||||
}
|
||||
return sv.AtLeast(v), nil
|
||||
}
|
||||
|
@ -103,12 +103,12 @@ func GetSigner(provider string) (ssh.Signer, error) {
|
||||
func makePrivateKeySignerFromFile(key string) (ssh.Signer, error) {
|
||||
buffer, err := os.ReadFile(key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading SSH key %s: '%v'", key, err)
|
||||
return nil, fmt.Errorf("error reading SSH key %s: %w", key, err)
|
||||
}
|
||||
|
||||
signer, err := ssh.ParsePrivateKey(buffer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing SSH key: '%v'", err)
|
||||
return nil, fmt.Errorf("error parsing SSH key: %w", err)
|
||||
}
|
||||
|
||||
return signer, err
|
||||
@ -201,7 +201,7 @@ func SSH(ctx context.Context, cmd, host, provider string) (Result, error) {
|
||||
// Get a signer for the provider.
|
||||
signer, err := GetSigner(provider)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("error getting signer for provider %s: '%v'", provider, err)
|
||||
return result, fmt.Errorf("error getting signer for provider %s: %w", provider, err)
|
||||
}
|
||||
|
||||
// RunSSHCommand will default to Getenv("USER") if user == "", but we're
|
||||
@ -250,12 +250,12 @@ func runSSHCommand(ctx context.Context, cmd, user, host string, signer ssh.Signe
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
return "", "", 0, fmt.Errorf("error getting SSH client to %s@%s: '%v'", user, host, err)
|
||||
return "", "", 0, fmt.Errorf("error getting SSH client to %s@%s: %w", user, host, err)
|
||||
}
|
||||
defer client.Close()
|
||||
session, err := client.NewSession()
|
||||
if err != nil {
|
||||
return "", "", 0, fmt.Errorf("error creating session to %s@%s: '%v'", user, host, err)
|
||||
return "", "", 0, fmt.Errorf("error creating session to %s@%s: %w", user, host, err)
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
@ -275,7 +275,7 @@ func runSSHCommand(ctx context.Context, cmd, user, host string, signer ssh.Signe
|
||||
} else {
|
||||
// Some other kind of error happened (e.g. an IOError); consider the
|
||||
// SSH unsuccessful.
|
||||
err = fmt.Errorf("failed running `%s` on %s@%s: '%v'", cmd, user, host, err)
|
||||
err = fmt.Errorf("failed running `%s` on %s@%s: %w", cmd, user, host, err)
|
||||
}
|
||||
}
|
||||
return bout.String(), berr.String(), code, err
|
||||
@ -304,26 +304,26 @@ func runSSHCommandViaBastion(ctx context.Context, cmd, user, bastion, host strin
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
return "", "", 0, fmt.Errorf("error getting SSH client to %s@%s: %v", user, bastion, err)
|
||||
return "", "", 0, fmt.Errorf("error getting SSH client to %s@%s: %w", user, bastion, err)
|
||||
}
|
||||
defer bastionClient.Close()
|
||||
|
||||
conn, err := bastionClient.Dial("tcp", host)
|
||||
if err != nil {
|
||||
return "", "", 0, fmt.Errorf("error dialing %s from bastion: %v", host, err)
|
||||
return "", "", 0, fmt.Errorf("error dialing %s from bastion: %w", host, err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
ncc, chans, reqs, err := ssh.NewClientConn(conn, host, config)
|
||||
if err != nil {
|
||||
return "", "", 0, fmt.Errorf("error creating forwarding connection %s from bastion: %v", host, err)
|
||||
return "", "", 0, fmt.Errorf("error creating forwarding connection %s from bastion: %w", host, err)
|
||||
}
|
||||
client := ssh.NewClient(ncc, chans, reqs)
|
||||
defer client.Close()
|
||||
|
||||
session, err := client.NewSession()
|
||||
if err != nil {
|
||||
return "", "", 0, fmt.Errorf("error creating session to %s@%s from bastion: '%v'", user, host, err)
|
||||
return "", "", 0, fmt.Errorf("error creating session to %s@%s from bastion: %w", user, host, err)
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
@ -343,7 +343,7 @@ func runSSHCommandViaBastion(ctx context.Context, cmd, user, bastion, host strin
|
||||
} else {
|
||||
// Some other kind of error happened (e.g. an IOError); consider the
|
||||
// SSH unsuccessful.
|
||||
err = fmt.Errorf("failed running `%s` on %s@%s: '%v'", cmd, user, host, err)
|
||||
err = fmt.Errorf("failed running `%s` on %s@%s: %w", cmd, user, host, err)
|
||||
}
|
||||
}
|
||||
return bout.String(), berr.String(), code, err
|
||||
|
@ -215,7 +215,7 @@ func CheckMount(ctx context.Context, c clientset.Interface, ss *appsv1.StatefulS
|
||||
fmt.Sprintf("touch %v", filepath.Join(mountPath, fmt.Sprintf("%v", time.Now().UnixNano()))),
|
||||
} {
|
||||
if err := ExecInStatefulPods(ctx, c, ss, cmd); err != nil {
|
||||
return fmt.Errorf("failed to execute %v, error: %v", cmd, err)
|
||||
return fmt.Errorf("failed to execute %v, error: %w", cmd, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -73,7 +73,7 @@ func Read(filePath string) ([]byte, error) {
|
||||
for _, filesource := range filesources {
|
||||
data, err := filesource.ReadTestFile(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fatal error retrieving test file %s: %s", filePath, err)
|
||||
return nil, fmt.Errorf("fatal error retrieving test file %s: %w", filePath, err)
|
||||
}
|
||||
if data != nil {
|
||||
return data, nil
|
||||
|
@ -51,7 +51,6 @@ import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
clientexec "k8s.io/client-go/util/exec"
|
||||
@ -464,7 +463,7 @@ func runVolumeTesterPod(ctx context.Context, client clientset.Interface, timeout
|
||||
}
|
||||
if err != nil {
|
||||
e2epod.DeletePodOrFail(ctx, client, clientPod.Namespace, clientPod.Name)
|
||||
_ = e2epod.WaitForPodToDisappear(ctx, client, clientPod.Namespace, clientPod.Name, labels.Everything(), framework.Poll, timeouts.PodDelete)
|
||||
_ = e2epod.WaitForPodNotFoundInNamespace(ctx, client, clientPod.Namespace, clientPod.Name, timeouts.PodDelete)
|
||||
return nil, err
|
||||
}
|
||||
return clientPod, nil
|
||||
@ -542,7 +541,7 @@ func testVolumeClient(ctx context.Context, f *framework.Framework, config TestCo
|
||||
// testVolumeClient might get used more than once per test, therefore
|
||||
// we have to clean up before returning.
|
||||
e2epod.DeletePodOrFail(ctx, f.ClientSet, clientPod.Namespace, clientPod.Name)
|
||||
framework.ExpectNoError(e2epod.WaitForPodToDisappear(ctx, f.ClientSet, clientPod.Namespace, clientPod.Name, labels.Everything(), framework.Poll, timeouts.PodDelete))
|
||||
framework.ExpectNoError(e2epod.WaitForPodNotFoundInNamespace(ctx, f.ClientSet, clientPod.Namespace, clientPod.Name, timeouts.PodDelete))
|
||||
}()
|
||||
|
||||
testVolumeContent(f, clientPod, "", fsGroup, fsType, tests)
|
||||
@ -577,7 +576,7 @@ func InjectContent(ctx context.Context, f *framework.Framework, config TestConfi
|
||||
// This pod must get deleted before the function returns becaue the test relies on
|
||||
// the volume not being in use.
|
||||
e2epod.DeletePodOrFail(ctx, f.ClientSet, injectorPod.Namespace, injectorPod.Name)
|
||||
framework.ExpectNoError(e2epod.WaitForPodToDisappear(ctx, f.ClientSet, injectorPod.Namespace, injectorPod.Name, labels.Everything(), framework.Poll, timeouts.PodDelete))
|
||||
framework.ExpectNoError(e2epod.WaitForPodNotFoundInNamespace(ctx, f.ClientSet, injectorPod.Namespace, injectorPod.Name, timeouts.PodDelete))
|
||||
}()
|
||||
|
||||
ginkgo.By("Writing text file contents in the container.")
|
||||
|
@ -40,7 +40,7 @@ func (rt *extractRT) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
func OpenWebSocketForURL(url *url.URL, config *restclient.Config, protocols []string) (*websocket.Conn, error) {
|
||||
tlsConfig, err := restclient.TLSConfigFor(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to create tls config: %v", err)
|
||||
return nil, fmt.Errorf("Failed to create tls config: %w", err)
|
||||
}
|
||||
if url.Scheme == "https" {
|
||||
url.Scheme = "wss"
|
||||
@ -49,11 +49,11 @@ func OpenWebSocketForURL(url *url.URL, config *restclient.Config, protocols []st
|
||||
}
|
||||
headers, err := headersForConfig(config, url)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to load http headers: %v", err)
|
||||
return nil, fmt.Errorf("Failed to load http headers: %w", err)
|
||||
}
|
||||
cfg, err := websocket.NewConfig(url.String(), "http://localhost")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to create websocket config: %v", err)
|
||||
return nil, fmt.Errorf("Failed to create websocket config: %w", err)
|
||||
}
|
||||
cfg.Header = headers
|
||||
cfg.TlsConfig = tlsConfig
|
||||
|
@ -46,7 +46,7 @@ var _ = instrumentation.SIGDescribe("MetricsGrabber", func() {
|
||||
gomega.Eventually(ctx, func() error {
|
||||
grabber, err = e2emetrics.NewMetricsGrabber(ctx, c, ec, f.ClientConfig(), true, true, true, true, true, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create metrics grabber: %v", err)
|
||||
return fmt.Errorf("failed to create metrics grabber: %w", err)
|
||||
}
|
||||
return nil
|
||||
}, 5*time.Minute, 10*time.Second).Should(gomega.BeNil())
|
||||
|
@ -120,7 +120,7 @@ func verifyPodExists(response []byte, containerName string) (bool, error) {
|
||||
var metadata Metadata
|
||||
err := json.Unmarshal(response, &metadata)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Failed to unmarshall: %s", err)
|
||||
return false, fmt.Errorf("Failed to unmarshall: %w", err)
|
||||
}
|
||||
|
||||
for _, result := range metadata.Results {
|
||||
@ -130,7 +130,7 @@ func verifyPodExists(response []byte, containerName string) (bool, error) {
|
||||
}
|
||||
resource, err := parseResource(rawResource)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("No 'resource' label: %s", err)
|
||||
return false, fmt.Errorf("No 'resource' label: %w", err)
|
||||
}
|
||||
if resource.resourceType == "k8s_container" &&
|
||||
resource.resourceLabels["container_name"] == containerName {
|
||||
|
@ -411,7 +411,7 @@ var _ = SIGDescribe("Kubectl client", func() {
|
||||
ginkgo.By(fmt.Sprintf("creating the pod from %v", podYaml))
|
||||
podYaml = commonutils.SubstituteImageName(string(readTestFileOrDie("pod-with-readiness-probe.yaml.in")))
|
||||
e2ekubectl.RunKubectlOrDieInput(ns, podYaml, "create", "-f", "-")
|
||||
framework.ExpectEqual(e2epod.CheckPodsRunningReady(ctx, c, ns, []string{simplePodName}, framework.PodStartTimeout), true)
|
||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(ctx, c, simplePodName, ns, framework.PodStartTimeout))
|
||||
})
|
||||
ginkgo.AfterEach(func() {
|
||||
cleanupKubectlInputs(podYaml, ns, simplePodSelector)
|
||||
@ -734,7 +734,7 @@ metadata:
|
||||
if !strings.Contains(ee.String(), "timed out") {
|
||||
framework.Failf("Missing expected 'timed out' error, got: %#v", ee)
|
||||
}
|
||||
framework.ExpectNoError(e2epod.WaitForPodToDisappear(ctx, f.ClientSet, ns, "failure-3", labels.Everything(), 2*time.Second, 2*v1.DefaultTerminationGracePeriodSeconds*time.Second))
|
||||
framework.ExpectNoError(e2epod.WaitForPodNotFoundInNamespace(ctx, f.ClientSet, ns, "failure-3", 2*v1.DefaultTerminationGracePeriodSeconds*time.Second))
|
||||
})
|
||||
|
||||
ginkgo.It("[Slow] running a failing command with --leave-stdin-open", func(ctx context.Context) {
|
||||
@ -798,9 +798,7 @@ metadata:
|
||||
g := func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) }
|
||||
runTestPod, _, err := polymorphichelpers.GetFirstPod(f.ClientSet.CoreV1(), ns, "run=run-test-3", 1*time.Minute, g)
|
||||
framework.ExpectNoError(err)
|
||||
if !e2epod.CheckPodsRunningReady(ctx, c, ns, []string{runTestPod.Name}, time.Minute) {
|
||||
framework.Failf("Pod %q of Job %q should still be running", runTestPod.Name, "run-test-3")
|
||||
}
|
||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(ctx, c, runTestPod.Name, ns, time.Minute))
|
||||
|
||||
gomega.Expect(c.CoreV1().Pods(ns).Delete(ctx, "run-test-3", metav1.DeleteOptions{})).To(gomega.BeNil())
|
||||
})
|
||||
@ -1384,7 +1382,7 @@ metadata:
|
||||
err := wait.PollImmediate(time.Second, time.Minute, func() (bool, error) {
|
||||
cj, err := c.BatchV1().CronJobs(ns).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Failed getting CronJob %s: %v", ns, err)
|
||||
return false, fmt.Errorf("Failed getting CronJob %s: %w", ns, err)
|
||||
}
|
||||
return len(cj.Items) > 0, nil
|
||||
})
|
||||
@ -1500,7 +1498,7 @@ metadata:
|
||||
ginkgo.By("creating the pod")
|
||||
podYaml = commonutils.SubstituteImageName(string(readTestFileOrDie("pause-pod.yaml.in")))
|
||||
e2ekubectl.RunKubectlOrDieInput(ns, podYaml, "create", "-f", "-")
|
||||
framework.ExpectEqual(e2epod.CheckPodsRunningReady(ctx, c, ns, []string{pausePodName}, framework.PodStartTimeout), true)
|
||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(ctx, c, pausePodName, ns, framework.PodStartTimeout))
|
||||
})
|
||||
ginkgo.AfterEach(func() {
|
||||
cleanupKubectlInputs(podYaml, ns, pausePodSelector)
|
||||
@ -1539,7 +1537,7 @@ metadata:
|
||||
ginkgo.By("creating the pod")
|
||||
podYaml = commonutils.SubstituteImageName(string(readTestFileOrDie("busybox-pod.yaml.in")))
|
||||
e2ekubectl.RunKubectlOrDieInput(ns, podYaml, "create", "-f", "-")
|
||||
framework.ExpectEqual(e2epod.CheckPodsRunningReady(ctx, c, ns, []string{busyboxPodName}, framework.PodStartTimeout), true)
|
||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(ctx, c, busyboxPodName, ns, framework.PodStartTimeout))
|
||||
})
|
||||
ginkgo.AfterEach(func() {
|
||||
cleanupKubectlInputs(podYaml, ns, busyboxPodSelector)
|
||||
@ -2028,11 +2026,11 @@ func checkContainersImage(containers []v1.Container, expectImage string) bool {
|
||||
func getAPIVersions(apiEndpoint string) (*metav1.APIVersions, error) {
|
||||
body, err := curl(apiEndpoint)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed http.Get of %s: %v", apiEndpoint, err)
|
||||
return nil, fmt.Errorf("Failed http.Get of %s: %w", apiEndpoint, err)
|
||||
}
|
||||
var apiVersions metav1.APIVersions
|
||||
if err := json.Unmarshal([]byte(body), &apiVersions); err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse /api output %s: %v", body, err)
|
||||
return nil, fmt.Errorf("Failed to parse /api output %s: %w", body, err)
|
||||
}
|
||||
return &apiVersions, nil
|
||||
}
|
||||
@ -2050,7 +2048,7 @@ func startProxyServer(ns string) (int, *exec.Cmd, error) {
|
||||
buf := make([]byte, 128)
|
||||
var n int
|
||||
if n, err = stdout.Read(buf); err != nil {
|
||||
return -1, cmd, fmt.Errorf("Failed to read from kubectl proxy stdout: %v", err)
|
||||
return -1, cmd, fmt.Errorf("Failed to read from kubectl proxy stdout: %w", err)
|
||||
}
|
||||
output := string(buf[:n])
|
||||
match := proxyRegexp.FindStringSubmatch(output)
|
||||
@ -2268,17 +2266,17 @@ func newBlockingReader(s string) (io.Reader, io.Closer, error) {
|
||||
func createApplyCustomResource(resource, namespace, name string, crd *crd.TestCrd) error {
|
||||
ginkgo.By("successfully create CR")
|
||||
if _, err := e2ekubectl.RunKubectlInput(namespace, resource, "create", "--validate=true", "-f", "-"); err != nil {
|
||||
return fmt.Errorf("failed to create CR %s in namespace %s: %v", resource, namespace, err)
|
||||
return fmt.Errorf("failed to create CR %s in namespace %s: %w", resource, namespace, err)
|
||||
}
|
||||
if _, err := e2ekubectl.RunKubectl(namespace, "delete", crd.Crd.Spec.Names.Plural, name); err != nil {
|
||||
return fmt.Errorf("failed to delete CR %s: %v", name, err)
|
||||
return fmt.Errorf("failed to delete CR %s: %w", name, err)
|
||||
}
|
||||
ginkgo.By("successfully apply CR")
|
||||
if _, err := e2ekubectl.RunKubectlInput(namespace, resource, "apply", "--validate=true", "-f", "-"); err != nil {
|
||||
return fmt.Errorf("failed to apply CR %s in namespace %s: %v", resource, namespace, err)
|
||||
return fmt.Errorf("failed to apply CR %s in namespace %s: %w", resource, namespace, err)
|
||||
}
|
||||
if _, err := e2ekubectl.RunKubectl(namespace, "delete", crd.Crd.Spec.Names.Plural, name); err != nil {
|
||||
return fmt.Errorf("failed to delete CR %s: %v", name, err)
|
||||
return fmt.Errorf("failed to delete CR %s: %w", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -389,7 +389,7 @@ func doTestOverWebSockets(ctx context.Context, bindAddress string, f *framework.
|
||||
gomega.Eventually(ctx, func() error {
|
||||
channel, msg, err := wsRead(ws)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read completely from websocket %s: %v", url.String(), err)
|
||||
return fmt.Errorf("failed to read completely from websocket %s: %w", url.String(), err)
|
||||
}
|
||||
if channel != 0 {
|
||||
return fmt.Errorf("got message from server that didn't start with channel 0 (data): %v", msg)
|
||||
@ -403,7 +403,7 @@ func doTestOverWebSockets(ctx context.Context, bindAddress string, f *framework.
|
||||
gomega.Eventually(ctx, func() error {
|
||||
channel, msg, err := wsRead(ws)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read completely from websocket %s: %v", url.String(), err)
|
||||
return fmt.Errorf("failed to read completely from websocket %s: %w", url.String(), err)
|
||||
}
|
||||
if channel != 1 {
|
||||
return fmt.Errorf("got message from server that didn't start with channel 1 (error): %v", msg)
|
||||
@ -426,7 +426,7 @@ func doTestOverWebSockets(ctx context.Context, bindAddress string, f *framework.
|
||||
gomega.Eventually(ctx, func() error {
|
||||
channel, msg, err := wsRead(ws)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read completely from websocket %s: %v", url.String(), err)
|
||||
return fmt.Errorf("failed to read completely from websocket %s: %w", url.String(), err)
|
||||
}
|
||||
if channel != 0 {
|
||||
return fmt.Errorf("got message from server that didn't start with channel 0 (data): %v", msg)
|
||||
|
@ -116,7 +116,7 @@ var _ = common.SIGDescribe("ClusterDns [Feature:Example]", func() {
|
||||
options := metav1.ListOptions{LabelSelector: label.String()}
|
||||
pods, err := c.CoreV1().Pods(ns.Name).List(ctx, options)
|
||||
framework.ExpectNoError(err, "failed to list pods in namespace: %s", ns.Name)
|
||||
err = e2epod.PodsResponding(ctx, c, ns.Name, backendName, false, pods)
|
||||
err = e2epod.WaitForPodsResponding(ctx, c, ns.Name, backendName, false, 0, pods)
|
||||
framework.ExpectNoError(err, "waiting for all pods to respond")
|
||||
framework.Logf("found %d backend pods responding in namespace %s", len(pods.Items), ns.Name)
|
||||
|
||||
|
@ -233,7 +233,7 @@ var _ = common.SIGDescribe("KubeProxy", func() {
|
||||
}
|
||||
timeoutSeconds, err := strconv.Atoi(line[2])
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to convert matched timeout %s to integer: %v", line[2], err)
|
||||
return false, fmt.Errorf("failed to convert matched timeout %s to integer: %w", line[2], err)
|
||||
}
|
||||
if math.Abs(float64(timeoutSeconds-expectedTimeoutSeconds)) < epsilonSeconds {
|
||||
return true, nil
|
||||
|
@ -81,11 +81,11 @@ func getInternalIP(node *v1.Node) (string, error) {
|
||||
func getSubnetPrefix(ctx context.Context, c clientset.Interface) (*net.IPNet, error) {
|
||||
node, err := getReadySchedulableWorkerNode(ctx, c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting a ready schedulable worker Node, err: %v", err)
|
||||
return nil, fmt.Errorf("error getting a ready schedulable worker Node, err: %w", err)
|
||||
}
|
||||
internalIP, err := getInternalIP(node)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting Node internal IP, err: %v", err)
|
||||
return nil, fmt.Errorf("error getting Node internal IP, err: %w", err)
|
||||
}
|
||||
ip := netutils.ParseIPSloppy(internalIP)
|
||||
if ip == nil {
|
||||
|
@ -85,12 +85,12 @@ func iperf2ServerDeployment(ctx context.Context, client clientset.Interface, nam
|
||||
|
||||
deployment, err := client.AppsV1().Deployments(namespace).Create(ctx, deploymentSpec, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("deployment %q Create API error: %v", deploymentSpec.Name, err)
|
||||
return nil, fmt.Errorf("deployment %q Create API error: %w", deploymentSpec.Name, err)
|
||||
}
|
||||
framework.Logf("Waiting for deployment %q to complete", deploymentSpec.Name)
|
||||
err = e2edeployment.WaitForDeploymentComplete(client, deployment)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("deployment %q failed to complete: %v", deploymentSpec.Name, err)
|
||||
return nil, fmt.Errorf("deployment %q failed to complete: %w", deploymentSpec.Name, err)
|
||||
}
|
||||
|
||||
return deployment, nil
|
||||
@ -119,7 +119,7 @@ func iperf2ClientDaemonSet(ctx context.Context, client clientset.Interface, name
|
||||
|
||||
ds, err := client.AppsV1().DaemonSets(namespace).Create(ctx, spec, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("daemonset %s Create API error: %v", spec.Name, err)
|
||||
return nil, fmt.Errorf("daemonset %s Create API error: %w", spec.Name, err)
|
||||
}
|
||||
return ds, nil
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ func (f *IngressScaleFramework) PrepareScaleTest(ctx context.Context) error {
|
||||
Cloud: f.CloudConfig,
|
||||
}
|
||||
if err := f.GCEController.Init(ctx); err != nil {
|
||||
return fmt.Errorf("failed to initialize GCE controller: %v", err)
|
||||
return fmt.Errorf("failed to initialize GCE controller: %w", err)
|
||||
}
|
||||
|
||||
f.ScaleTestSvcs = []*v1.Service{}
|
||||
@ -137,7 +137,7 @@ func (f *IngressScaleFramework) CleanupScaleTest(ctx context.Context) []error {
|
||||
for _, ing := range f.ScaleTestIngs {
|
||||
if ing != nil {
|
||||
if err := f.Clientset.NetworkingV1().Ingresses(ing.Namespace).Delete(ctx, ing.Name, metav1.DeleteOptions{}); err != nil {
|
||||
errs = append(errs, fmt.Errorf("error while deleting ingress %s/%s: %v", ing.Namespace, ing.Name, err))
|
||||
errs = append(errs, fmt.Errorf("error while deleting ingress %s/%s: %w", ing.Namespace, ing.Name, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -145,14 +145,14 @@ func (f *IngressScaleFramework) CleanupScaleTest(ctx context.Context) []error {
|
||||
for _, svc := range f.ScaleTestSvcs {
|
||||
if svc != nil {
|
||||
if err := f.Clientset.CoreV1().Services(svc.Namespace).Delete(ctx, svc.Name, metav1.DeleteOptions{}); err != nil {
|
||||
errs = append(errs, fmt.Errorf("error while deleting service %s/%s: %v", svc.Namespace, svc.Name, err))
|
||||
errs = append(errs, fmt.Errorf("error while deleting service %s/%s: %w", svc.Namespace, svc.Name, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
if f.ScaleTestDeploy != nil {
|
||||
f.Logger.Infof("Cleaning up deployment %s...", f.ScaleTestDeploy.Name)
|
||||
if err := f.Clientset.AppsV1().Deployments(f.ScaleTestDeploy.Namespace).Delete(ctx, f.ScaleTestDeploy.Name, metav1.DeleteOptions{}); err != nil {
|
||||
errs = append(errs, fmt.Errorf("error while deleting deployment %s/%s: %v", f.ScaleTestDeploy.Namespace, f.ScaleTestDeploy.Name, err))
|
||||
errs = append(errs, fmt.Errorf("error while deleting deployment %s/%s: %w", f.ScaleTestDeploy.Namespace, f.ScaleTestDeploy.Name, err))
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ func (f *IngressScaleFramework) RunScaleTest(ctx context.Context) []error {
|
||||
f.Logger.Infof("Creating deployment %s...", testDeploy.Name)
|
||||
testDeploy, err := f.Jig.Client.AppsV1().Deployments(f.Namespace).Create(ctx, testDeploy, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to create deployment %s: %v", testDeploy.Name, err))
|
||||
errs = append(errs, fmt.Errorf("failed to create deployment %s: %w", testDeploy.Name, err))
|
||||
return errs
|
||||
}
|
||||
f.ScaleTestDeploy = testDeploy
|
||||
@ -180,7 +180,7 @@ func (f *IngressScaleFramework) RunScaleTest(ctx context.Context) []error {
|
||||
if f.EnableTLS {
|
||||
f.Logger.Infof("Ensuring TLS secret %s...", scaleTestSecretName)
|
||||
if err := f.Jig.PrepareTLSSecret(ctx, f.Namespace, scaleTestSecretName, scaleTestHostname); err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to prepare TLS secret %s: %v", scaleTestSecretName, err))
|
||||
errs = append(errs, fmt.Errorf("failed to prepare TLS secret %s: %w", scaleTestSecretName, err))
|
||||
return errs
|
||||
}
|
||||
}
|
||||
|
@ -4163,7 +4163,7 @@ func translatePodNameToUID(ctx context.Context, c clientset.Interface, ns string
|
||||
for name, portList := range expectedEndpoints {
|
||||
pod, err := c.CoreV1().Pods(ns).Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get pod %s, that's pretty weird. validation failed: %s", name, err)
|
||||
return nil, fmt.Errorf("failed to get pod %s, that's pretty weird. validation failed: %w", name, err)
|
||||
}
|
||||
portsByUID[pod.ObjectMeta.UID] = portList
|
||||
}
|
||||
@ -4249,14 +4249,14 @@ func restartApiserver(ctx context.Context, namespace string, cs clientset.Interf
|
||||
func restartComponent(ctx context.Context, cs clientset.Interface, cName, ns string, matchLabels map[string]string) error {
|
||||
pods, err := e2epod.GetPods(ctx, cs, ns, matchLabels)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get %s's pods, err: %v", cName, err)
|
||||
return fmt.Errorf("failed to get %s's pods, err: %w", cName, err)
|
||||
}
|
||||
if len(pods) == 0 {
|
||||
return fmt.Errorf("%s pod count is 0", cName)
|
||||
}
|
||||
|
||||
if err := e2epod.DeletePodsWithGracePeriod(ctx, cs, pods, 0); err != nil {
|
||||
return fmt.Errorf("failed to restart component: %s, err: %v", cName, err)
|
||||
return fmt.Errorf("failed to restart component: %s, err: %w", cName, err)
|
||||
}
|
||||
|
||||
_, err = e2epod.PodsCreatedByLabel(ctx, cs, ns, cName, int32(len(pods)), labels.SelectorFromSet(matchLabels))
|
||||
@ -4330,7 +4330,7 @@ func translatePortsByPodNameToPortsByPodUID(c clientset.Interface, ns string, ex
|
||||
for name, portList := range expectedEndpoints {
|
||||
pod, err := c.CoreV1().Pods(ns).Get(context.TODO(), name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get pod %s, that's pretty weird. validation failed: %s", name, err)
|
||||
return nil, fmt.Errorf("failed to get pod %s, that's pretty weird. validation failed: %w", name, err)
|
||||
}
|
||||
portsByUID[pod.ObjectMeta.UID] = portList
|
||||
}
|
||||
|
@ -869,7 +869,7 @@ func patchPod(cs clientset.Interface, old, new *v1.Pod) (*v1.Pod, error) {
|
||||
}
|
||||
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, &v1.Pod{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create merge patch for Pod %q: %v", old.Name, err)
|
||||
return nil, fmt.Errorf("failed to create merge patch for Pod %q: %w", old.Name, err)
|
||||
}
|
||||
return cs.CoreV1().Pods(new.Namespace).Patch(context.TODO(), new.Name, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{})
|
||||
}
|
||||
|
@ -930,7 +930,7 @@ func patchNode(ctx context.Context, client clientset.Interface, old *v1.Node, ne
|
||||
}
|
||||
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, &v1.Node{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create merge patch for node %q: %v", old.Name, err)
|
||||
return fmt.Errorf("failed to create merge patch for node %q: %w", old.Name, err)
|
||||
}
|
||||
_, err = client.CoreV1().Nodes().Patch(ctx, old.Name, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}, "status")
|
||||
return err
|
||||
@ -948,7 +948,7 @@ func patchPriorityClass(ctx context.Context, cs clientset.Interface, old, new *s
|
||||
}
|
||||
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, &schedulingv1.PriorityClass{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create merge patch for PriorityClass %q: %v", old.Name, err)
|
||||
return fmt.Errorf("failed to create merge patch for PriorityClass %q: %w", old.Name, err)
|
||||
}
|
||||
_, err = cs.SchedulingV1().PriorityClasses().Patch(ctx, old.Name, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{})
|
||||
return err
|
||||
|
@ -108,7 +108,7 @@ var _ = SIGDescribe("SchedulerPriorities [Serial]", func() {
|
||||
|
||||
err = framework.CheckTestingNSDeletedExcept(ctx, cs, ns)
|
||||
framework.ExpectNoError(err)
|
||||
err = e2epod.WaitForPodsRunningReady(ctx, cs, metav1.NamespaceSystem, int32(systemPodsNo), 0, framework.PodReadyBeforeTimeout, map[string]string{})
|
||||
err = e2epod.WaitForPodsRunningReady(ctx, cs, metav1.NamespaceSystem, int32(systemPodsNo), 0, framework.PodReadyBeforeTimeout)
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
// skip if the most utilized node has less than the cri-o minMemLimit available
|
||||
|
@ -180,7 +180,7 @@ var _ = utils.SIGDescribe("CSI Mock volume storage capacity", func() {
|
||||
err = wait.PollImmediateUntilWithContext(ctx, time.Second, func(ctx context.Context) (done bool, err error) {
|
||||
c, index, err := compareCSICalls(ctx, deterministicCalls, expected, m.driver.GetCalls)
|
||||
if err != nil {
|
||||
return true, fmt.Errorf("error waiting for expected CSI calls: %s", err)
|
||||
return true, fmt.Errorf("error waiting for expected CSI calls: %w", err)
|
||||
}
|
||||
calls = c
|
||||
if index == 0 {
|
||||
|
@ -416,7 +416,7 @@ func waitForResizeStatus(pvc *v1.PersistentVolumeClaim, c clientset.Interface, e
|
||||
updatedPVC, err := c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(context.TODO(), pvc.Name, metav1.GetOptions{})
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error fetching pvc %q for checking for resize status: %v", pvc.Name, err)
|
||||
return false, fmt.Errorf("error fetching pvc %q for checking for resize status: %w", pvc.Name, err)
|
||||
}
|
||||
|
||||
actualResizeStatus = updatedPVC.Status.ResizeStatus
|
||||
@ -442,7 +442,7 @@ func waitForAllocatedResource(pvc *v1.PersistentVolumeClaim, m *mockDriverSetup,
|
||||
updatedPVC, err := m.cs.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(context.TODO(), pvc.Name, metav1.GetOptions{})
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error fetching pvc %q for checking for resize status: %v", pvc.Name, err)
|
||||
return false, fmt.Errorf("error fetching pvc %q for checking for resize status: %w", pvc.Name, err)
|
||||
}
|
||||
actualAllocatedSize := updatedPVC.Status.AllocatedResources.Storage()
|
||||
if actualAllocatedSize != nil && actualAllocatedSize.Equal(expectedQuantity) {
|
||||
|
@ -751,7 +751,7 @@ func (m *mockCSIDriver) GetCalls(ctx context.Context) ([]MockCSICall, error) {
|
||||
// Load logs of driver pod
|
||||
log, err := e2epod.GetPodLogs(ctx, m.clientSet, m.driverNamespace.Name, driverPodName, driverContainerName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not load CSI driver logs: %s", err)
|
||||
return nil, fmt.Errorf("could not load CSI driver logs: %w", err)
|
||||
}
|
||||
|
||||
logLines := strings.Split(log, "\n")
|
||||
|
@ -75,7 +75,7 @@ func (p PodDirIO) CreateFile(path string, content io.Reader) error {
|
||||
// Therefore the content is now encoded inside the command itself.
|
||||
data, err := io.ReadAll(content)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read content: %v", err)
|
||||
return fmt.Errorf("read content: %w", err)
|
||||
}
|
||||
encoded := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
|
||||
base64.StdEncoding.Encode(encoded, data)
|
||||
|
@ -97,7 +97,7 @@ func Listen(ctx context.Context, clientset kubernetes.Interface, restConfig *res
|
||||
SubResource("portforward")
|
||||
transport, upgrader, err := spdy.RoundTripperFor(restConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create round tripper: %v", err)
|
||||
return nil, fmt.Errorf("create round tripper: %w", err)
|
||||
}
|
||||
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", req.URL())
|
||||
|
||||
@ -212,7 +212,7 @@ type stream struct {
|
||||
func dial(ctx context.Context, prefix string, dialer httpstream.Dialer, port int) (s *stream, finalErr error) {
|
||||
streamConn, _, err := dialer.Dial(portforward.PortForwardProtocolV1Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("dialer failed: %v", err)
|
||||
return nil, fmt.Errorf("dialer failed: %w", err)
|
||||
}
|
||||
requestID := "1"
|
||||
defer func() {
|
||||
@ -231,7 +231,7 @@ func dial(ctx context.Context, prefix string, dialer httpstream.Dialer, port int
|
||||
// This happens asynchronously.
|
||||
errorStream, err := streamConn.CreateStream(headers)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating error stream: %v", err)
|
||||
return nil, fmt.Errorf("error creating error stream: %w", err)
|
||||
}
|
||||
errorStream.Close()
|
||||
go func() {
|
||||
@ -248,7 +248,7 @@ func dial(ctx context.Context, prefix string, dialer httpstream.Dialer, port int
|
||||
headers.Set(v1.StreamType, v1.StreamTypeData)
|
||||
dataStream, err := streamConn.CreateStream(headers)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating data stream: %v", err)
|
||||
return nil, fmt.Errorf("error creating data stream: %w", err)
|
||||
}
|
||||
|
||||
return &stream{
|
||||
|
@ -26,7 +26,6 @@ import (
|
||||
|
||||
"github.com/onsi/ginkgo/v2"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
|
||||
@ -197,11 +196,6 @@ var _ = utils.SIGDescribe("Flexvolumes", func() {
|
||||
|
||||
testFlexVolume(ctx, driverInstallAs, config, f)
|
||||
|
||||
ginkgo.By("waiting for flex client pod to terminate")
|
||||
if err := e2epod.WaitForPodTerminatedInNamespace(ctx, f.ClientSet, config.Prefix+"-client", "", f.Namespace.Name); !apierrors.IsNotFound(err) {
|
||||
framework.ExpectNoError(err, "Failed to wait client pod terminated: %v", err)
|
||||
}
|
||||
|
||||
ginkgo.By(fmt.Sprintf("uninstalling flexvolume %s from node %s", driverInstallAs, node.Name))
|
||||
uninstallFlex(ctx, cs, node, "k8s", driverInstallAs)
|
||||
})
|
||||
@ -217,11 +211,6 @@ var _ = utils.SIGDescribe("Flexvolumes", func() {
|
||||
|
||||
testFlexVolume(ctx, driverInstallAs, config, f)
|
||||
|
||||
ginkgo.By("waiting for flex client pod to terminate")
|
||||
if err := e2epod.WaitForPodTerminatedInNamespace(ctx, f.ClientSet, config.Prefix+"-client", "", f.Namespace.Name); !apierrors.IsNotFound(err) {
|
||||
framework.ExpectNoError(err, "Failed to wait client pod terminated: %v", err)
|
||||
}
|
||||
|
||||
// Detach might occur after pod deletion. Wait before deleting driver.
|
||||
time.Sleep(detachTimeout)
|
||||
|
||||
|
@ -178,17 +178,17 @@ func createNginxPod(ctx context.Context, client clientset.Interface, namespace s
|
||||
pod := makeNginxPod(namespace, nodeSelector, pvclaims)
|
||||
pod, err := client.CoreV1().Pods(namespace).Create(ctx, pod, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pod Create API error: %v", err)
|
||||
return nil, fmt.Errorf("pod Create API error: %w", err)
|
||||
}
|
||||
// Waiting for pod to be running
|
||||
err = e2epod.WaitForPodNameRunningInNamespace(ctx, client, pod.Name, namespace)
|
||||
if err != nil {
|
||||
return pod, fmt.Errorf("pod %q is not Running: %v", pod.Name, err)
|
||||
return pod, fmt.Errorf("pod %q is not Running: %w", pod.Name, err)
|
||||
}
|
||||
// get fresh pod info
|
||||
pod, err = client.CoreV1().Pods(namespace).Get(ctx, pod.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return pod, fmt.Errorf("pod Get API error: %v", err)
|
||||
return pod, fmt.Errorf("pod Get API error: %w", err)
|
||||
}
|
||||
return pod, nil
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ func UpdatePVSize(ctx context.Context, pv *v1.PersistentVolume, size resource.Qu
|
||||
var err error
|
||||
pvToUpdate, err = c.CoreV1().PersistentVolumes().Get(ctx, pvName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error fetching pv %s: %v", pvName, err)
|
||||
return false, fmt.Errorf("error fetching pv %s: %w", pvName, err)
|
||||
}
|
||||
pvToUpdate.Spec.Capacity[v1.ResourceStorage] = size
|
||||
pvToUpdate, err = c.CoreV1().PersistentVolumes().Update(ctx, pvToUpdate, metav1.UpdateOptions{})
|
||||
|
@ -165,7 +165,7 @@ func waitForDeploymentToRecreatePod(ctx context.Context, client clientset.Interf
|
||||
waitErr := wait.PollImmediate(10*time.Second, 5*time.Minute, func() (bool, error) {
|
||||
podList, err := e2edeployment.GetPodsForDeployment(ctx, client, deployment)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get pods for deployment: %v", err)
|
||||
return false, fmt.Errorf("failed to get pods for deployment: %w", err)
|
||||
}
|
||||
for _, pod := range podList.Items {
|
||||
switch pod.Status.Phase {
|
||||
|
@ -35,7 +35,6 @@ import (
|
||||
"k8s.io/kubernetes/test/e2e/storage/drivers"
|
||||
storageframework "k8s.io/kubernetes/test/e2e/storage/framework"
|
||||
"k8s.io/kubernetes/test/e2e/storage/utils"
|
||||
testutils "k8s.io/kubernetes/test/utils"
|
||||
imageutils "k8s.io/kubernetes/test/utils/image"
|
||||
admissionapi "k8s.io/pod-security-admission/api"
|
||||
)
|
||||
@ -119,7 +118,7 @@ var _ = utils.SIGDescribe("[Feature:NodeOutOfServiceVolumeDetach] [Disruptive] [
|
||||
LabelSelector: labelSelectorStr,
|
||||
FieldSelector: fields.OneTermNotEqualSelector("spec.nodeName", oldNodeName).String(),
|
||||
}
|
||||
_, err = e2epod.WaitForAllPodsCondition(ctx, c, ns, podListOpts, 1, "running and ready", framework.PodStartTimeout, testutils.PodRunningReady)
|
||||
_, err = e2epod.WaitForPods(ctx, c, ns, podListOpts, e2epod.Range{MinMatching: 1}, framework.PodStartTimeout, "be running and ready", e2epod.RunningReady)
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
// Bring the node back online and remove the taint
|
||||
|
@ -33,7 +33,6 @@ import (
|
||||
policyv1 "k8s.io/api/policy/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
@ -196,7 +195,7 @@ var _ = utils.SIGDescribe("Pod Disks [Feature:StorageProvider]", func() {
|
||||
ginkgo.By("deleting host0Pod") // delete this pod before creating next pod
|
||||
framework.ExpectNoError(podClient.Delete(ctx, host0Pod.Name, podDelOpt), "Failed to delete host0Pod")
|
||||
framework.Logf("deleted host0Pod %q", host0Pod.Name)
|
||||
e2epod.WaitForPodToDisappear(ctx, cs, host0Pod.Namespace, host0Pod.Name, labels.Everything(), framework.Poll, f.Timeouts.PodDelete)
|
||||
e2epod.WaitForPodNotFoundInNamespace(ctx, cs, host0Pod.Namespace, host0Pod.Name, f.Timeouts.PodDelete)
|
||||
framework.Logf("deleted host0Pod %q disappeared", host0Pod.Name)
|
||||
}
|
||||
|
||||
@ -527,7 +526,7 @@ func detachPD(nodeName types.NodeName, pdName string) error {
|
||||
} else if framework.TestContext.Provider == "aws" {
|
||||
awsSession, err := session.NewSession()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating session: %v", err)
|
||||
return fmt.Errorf("error creating session: %w", err)
|
||||
}
|
||||
client := ec2.New(awsSession)
|
||||
tokens := strings.Split(pdName, "/")
|
||||
@ -537,7 +536,7 @@ func detachPD(nodeName types.NodeName, pdName string) error {
|
||||
}
|
||||
_, err = client.DetachVolume(&request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error detaching EBS volume: %v", err)
|
||||
return fmt.Errorf("error detaching EBS volume: %w", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@ -562,7 +561,7 @@ func attachPD(nodeName types.NodeName, pdName string) error {
|
||||
} else if framework.TestContext.Provider == "aws" {
|
||||
awsSession, err := session.NewSession()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating session: %v", err)
|
||||
return fmt.Errorf("error creating session: %w", err)
|
||||
}
|
||||
client := ec2.New(awsSession)
|
||||
tokens := strings.Split(pdName, "/")
|
||||
@ -570,7 +569,7 @@ func attachPD(nodeName types.NodeName, pdName string) error {
|
||||
ebsUtil := utils.NewEBSUtil(client)
|
||||
err = ebsUtil.AttachDisk(awsVolumeID, string(nodeName))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error attaching volume %s to node %s: %v", awsVolumeID, nodeName, err)
|
||||
return fmt.Errorf("error attaching volume %s to node %s: %w", awsVolumeID, nodeName, err)
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
|
@ -959,7 +959,7 @@ func createLocalPVCsPVs(ctx context.Context, config *localTestConfig, volumes []
|
||||
for _, volume := range volumes {
|
||||
pvc, err := config.client.CoreV1().PersistentVolumeClaims(volume.pvc.Namespace).Get(ctx, volume.pvc.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get PVC %s/%s: %v", volume.pvc.Namespace, volume.pvc.Name, err)
|
||||
return false, fmt.Errorf("failed to get PVC %s/%s: %w", volume.pvc.Namespace, volume.pvc.Name, err)
|
||||
}
|
||||
if pvc.Status.Phase != v1.ClaimPending {
|
||||
return true, nil
|
||||
|
@ -70,7 +70,7 @@ func completeMultiTest(ctx context.Context, f *framework.Framework, c clientset.
|
||||
for pvcKey := range claims {
|
||||
pvc, err := c.CoreV1().PersistentVolumeClaims(pvcKey.Namespace).Get(ctx, pvcKey.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting pvc %q: %v", pvcKey.Name, err)
|
||||
return fmt.Errorf("error getting pvc %q: %w", pvcKey.Name, err)
|
||||
}
|
||||
if len(pvc.Spec.VolumeName) == 0 {
|
||||
continue // claim is not bound
|
||||
@ -450,7 +450,7 @@ func createWaitAndDeletePod(ctx context.Context, c clientset.Interface, t *frame
|
||||
pod := e2epod.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, command)
|
||||
runPod, err := c.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("pod Create API error: %v", err)
|
||||
return fmt.Errorf("pod Create API error: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
delErr := e2epod.DeletePodWithWait(ctx, c, runPod)
|
||||
@ -461,7 +461,7 @@ func createWaitAndDeletePod(ctx context.Context, c clientset.Interface, t *frame
|
||||
|
||||
err = testPodSuccessOrFail(ctx, c, t, ns, runPod)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pod %q did not exit with Success: %v", runPod.Name, err)
|
||||
return fmt.Errorf("pod %q did not exit with Success: %w", runPod.Name, err)
|
||||
}
|
||||
return // note: named return value
|
||||
}
|
||||
@ -470,7 +470,7 @@ func createWaitAndDeletePod(ctx context.Context, c clientset.Interface, t *frame
|
||||
func testPodSuccessOrFail(ctx context.Context, c clientset.Interface, t *framework.TimeoutContext, ns string, pod *v1.Pod) error {
|
||||
framework.Logf("Pod should terminate with exitcode 0 (success)")
|
||||
if err := e2epod.WaitForPodSuccessInNamespaceTimeout(ctx, c, pod.Name, ns, t.PodStart); err != nil {
|
||||
return fmt.Errorf("pod %q failed to reach Success: %v", pod.Name, err)
|
||||
return fmt.Errorf("pod %q failed to reach Success: %w", pod.Name, err)
|
||||
}
|
||||
framework.Logf("Pod %v succeeded ", pod.Name)
|
||||
return nil
|
||||
|
@ -176,7 +176,7 @@ func waitForPVCStorageClass(ctx context.Context, c clientset.Interface, namespac
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return watchedPVC, fmt.Errorf("error waiting for claim %s to have StorageClass set to %s: %v", pvcName, scName, err)
|
||||
return watchedPVC, fmt.Errorf("error waiting for claim %s to have StorageClass set to %s: %w", pvcName, scName, err)
|
||||
}
|
||||
|
||||
return watchedPVC, nil
|
||||
|
@ -33,7 +33,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
@ -846,7 +845,7 @@ func (t StorageClassTest) TestBindingWaitForFirstConsumerMultiPVC(ctx context.Co
|
||||
framework.ExpectNoError(err)
|
||||
ginkgo.DeferCleanup(func(ctx context.Context) error {
|
||||
e2epod.DeletePodOrFail(ctx, t.Client, pod.Namespace, pod.Name)
|
||||
return e2epod.WaitForPodToDisappear(ctx, t.Client, pod.Namespace, pod.Name, labels.Everything(), framework.Poll, t.Timeouts.PodDelete)
|
||||
return e2epod.WaitForPodNotFoundInNamespace(ctx, t.Client, pod.Namespace, pod.Name, t.Timeouts.PodDelete)
|
||||
})
|
||||
if expectUnschedulable {
|
||||
// Verify that no claims are provisioned.
|
||||
|
@ -303,7 +303,7 @@ func ExpandPVCSize(ctx context.Context, origPVC *v1.PersistentVolumeClaim, size
|
||||
var err error
|
||||
updatedPVC, err = c.CoreV1().PersistentVolumeClaims(origPVC.Namespace).Get(ctx, pvcName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error fetching pvc %q for resizing: %v", pvcName, err)
|
||||
return false, fmt.Errorf("error fetching pvc %q for resizing: %w", pvcName, err)
|
||||
}
|
||||
|
||||
updatedPVC.Spec.Resources.Requests[v1.ResourceStorage] = size
|
||||
@ -331,7 +331,7 @@ func WaitForResizingCondition(ctx context.Context, pvc *v1.PersistentVolumeClaim
|
||||
updatedPVC, err := c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(ctx, pvc.Name, metav1.GetOptions{})
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error fetching pvc %q for checking for resize status: %v", pvc.Name, err)
|
||||
return false, fmt.Errorf("error fetching pvc %q for checking for resize status: %w", pvc.Name, err)
|
||||
}
|
||||
|
||||
pvcConditions := updatedPVC.Status.Conditions
|
||||
@ -381,7 +381,7 @@ func WaitForPendingFSResizeCondition(ctx context.Context, pvc *v1.PersistentVolu
|
||||
updatedPVC, err = c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(ctx, pvc.Name, metav1.GetOptions{})
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error fetching pvc %q for checking for resize status : %v", pvc.Name, err)
|
||||
return false, fmt.Errorf("error fetching pvc %q for checking for resize status : %w", pvc.Name, err)
|
||||
}
|
||||
|
||||
inProgressConditions := updatedPVC.Status.Conditions
|
||||
@ -409,7 +409,7 @@ func WaitForFSResize(ctx context.Context, pvc *v1.PersistentVolumeClaim, c clien
|
||||
updatedPVC, err = c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(ctx, pvc.Name, metav1.GetOptions{})
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error fetching pvc %q for checking for resize status : %v", pvc.Name, err)
|
||||
return false, fmt.Errorf("error fetching pvc %q for checking for resize status : %w", pvc.Name, err)
|
||||
}
|
||||
|
||||
pvcSize := updatedPVC.Spec.Resources.Requests[v1.ResourceStorage]
|
||||
|
@ -263,7 +263,7 @@ func verifyFile(f *framework.Framework, pod *v1.Pod, fpath string, expectSize in
|
||||
}
|
||||
size, err := strconv.Atoi(strings.TrimSuffix(rtnstr, "\n"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to convert string %q to int: %v", rtnstr, err)
|
||||
return fmt.Errorf("unable to convert string %q to int: %w", rtnstr, err)
|
||||
}
|
||||
if int64(size) != expectSize {
|
||||
return fmt.Errorf("size of file %s is %d, expected %d", fpath, size, expectSize)
|
||||
@ -320,7 +320,7 @@ func testVolumeIO(ctx context.Context, f *framework.Framework, cs clientset.Inte
|
||||
podsNamespacer := cs.CoreV1().Pods(config.Namespace)
|
||||
clientPod, err = podsNamespacer.Create(ctx, clientPod, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create client pod %q: %v", clientPod.Name, err)
|
||||
return fmt.Errorf("failed to create client pod %q: %w", clientPod.Name, err)
|
||||
}
|
||||
ginkgo.DeferCleanup(func(ctx context.Context) {
|
||||
deleteFile(f, clientPod, ddInput)
|
||||
@ -339,7 +339,7 @@ func testVolumeIO(ctx context.Context, f *framework.Framework, cs clientset.Inte
|
||||
|
||||
err = e2epod.WaitTimeoutForPodRunningInNamespace(ctx, cs, clientPod.Name, clientPod.Namespace, f.Timeouts.PodStart)
|
||||
if err != nil {
|
||||
return fmt.Errorf("client pod %q not running: %v", clientPod.Name, err)
|
||||
return fmt.Errorf("client pod %q not running: %w", clientPod.Name, err)
|
||||
}
|
||||
|
||||
// create files of the passed-in file sizes and verify test file size and content
|
||||
|
@ -342,7 +342,7 @@ func waitForAllPVCsBound(ctx context.Context, cs clientset.Interface, timeout ti
|
||||
return true, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error waiting for all PVCs to be bound: %v", err)
|
||||
return nil, fmt.Errorf("error waiting for all PVCs to be bound: %w", err)
|
||||
}
|
||||
return pvNames, nil
|
||||
}
|
||||
@ -411,7 +411,7 @@ func getCSINodeLimits(ctx context.Context, cs clientset.Interface, config *stora
|
||||
return true, nil
|
||||
})
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not get CSINode limit for driver %s: %v", driverInfo.Name, err)
|
||||
return 0, fmt.Errorf("could not get CSINode limit for driver %s: %w", driverInfo.Name, err)
|
||||
}
|
||||
return limit, nil
|
||||
}
|
||||
|
@ -506,7 +506,7 @@ func listPodDirectory(ctx context.Context, h storageutils.HostExec, path string,
|
||||
cmd := fmt.Sprintf("find %s -mindepth 2 -maxdepth 2", path)
|
||||
out, err := h.IssueCommandWithResult(ctx, cmd, node)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error checking directory %s on node %s: %s", path, node.Name, err)
|
||||
return nil, fmt.Errorf("error checking directory %s on node %s: %w", path, node.Name, err)
|
||||
}
|
||||
return strings.Split(out, "\n"), nil
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
"github.com/onsi/ginkgo/v2"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
@ -101,7 +100,7 @@ func PodsUseStaticPVsOrFail(ctx context.Context, f *framework.Framework, podCoun
|
||||
go func(config *staticPVTestConfig) {
|
||||
defer ginkgo.GinkgoRecover()
|
||||
defer wg.Done()
|
||||
err := e2epod.WaitForPodToDisappear(ctx, c, ns, config.pod.Name, labels.Everything(), framework.Poll, f.Timeouts.PodDelete)
|
||||
err := e2epod.WaitForPodNotFoundInNamespace(ctx, c, ns, config.pod.Name, f.Timeouts.PodDelete)
|
||||
framework.ExpectNoError(err, "while waiting for pod to disappear")
|
||||
errs := e2epv.PVPVCCleanup(ctx, c, ns, config.pv, config.pvc)
|
||||
framework.ExpectNoError(utilerrors.NewAggregate(errs), "while cleaning up PVs and PVCs")
|
||||
|
@ -64,16 +64,16 @@ func NewEBSUtil(client *ec2.EC2) *EBSUtil {
|
||||
func (ebs *EBSUtil) AttachDisk(volumeID string, nodeName string) error {
|
||||
instance, err := findInstanceByNodeName(nodeName, ebs.client)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error finding node %s: %v", nodeName, err)
|
||||
return fmt.Errorf("error finding node %s: %w", nodeName, err)
|
||||
}
|
||||
err = ebs.waitForAvailable(volumeID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error waiting volume %s to be available: %v", volumeID, err)
|
||||
return fmt.Errorf("error waiting volume %s to be available: %w", volumeID, err)
|
||||
}
|
||||
|
||||
device, err := ebs.findFreeDevice(instance)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error finding free device on node %s: %v", nodeName, err)
|
||||
return fmt.Errorf("error finding free device on node %s: %w", nodeName, err)
|
||||
}
|
||||
hostDevice := "/dev/xvd" + string(device)
|
||||
attachInput := &ec2.AttachVolumeInput{
|
||||
@ -83,7 +83,7 @@ func (ebs *EBSUtil) AttachDisk(volumeID string, nodeName string) error {
|
||||
}
|
||||
_, err = ebs.client.AttachVolume(attachInput)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error attaching volume %s to node %s: %v", volumeID, nodeName, err)
|
||||
return fmt.Errorf("error attaching volume %s to node %s: %w", volumeID, nodeName, err)
|
||||
}
|
||||
return ebs.waitForAttach(volumeID)
|
||||
}
|
||||
@ -245,7 +245,7 @@ func describeInstances(request *ec2.DescribeInstancesInput, cloud *ec2.EC2) ([]*
|
||||
for {
|
||||
response, err := cloud.DescribeInstances(request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error listing AWS instances: %v", err)
|
||||
return nil, fmt.Errorf("error listing AWS instances: %w", err)
|
||||
}
|
||||
|
||||
for _, reservation := range response.Reservations {
|
||||
|
@ -72,7 +72,7 @@ func checkAWSEBS(volume *v1.PersistentVolume, volumeType string, encrypted bool)
|
||||
|
||||
awsSession, err := session.NewSession()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating session: %v", err)
|
||||
return fmt.Errorf("error creating session: %w", err)
|
||||
}
|
||||
|
||||
if len(zone) > 0 {
|
||||
@ -90,7 +90,7 @@ func checkAWSEBS(volume *v1.PersistentVolume, volumeType string, encrypted bool)
|
||||
}
|
||||
info, err := client.DescribeVolumes(request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error querying ec2 for volume %q: %v", volumeID, err)
|
||||
return fmt.Errorf("error querying ec2 for volume %q: %w", volumeID, err)
|
||||
}
|
||||
if len(info.Volumes) == 0 {
|
||||
return fmt.Errorf("no volumes found for volume %q", volumeID)
|
||||
@ -737,7 +737,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() {
|
||||
err = wait.Poll(time.Second, framework.ClaimProvisionTimeout, func() (bool, error) {
|
||||
events, err := c.CoreV1().Events(claim.Namespace).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("could not list PVC events in %s: %v", claim.Namespace, err)
|
||||
return false, fmt.Errorf("could not list PVC events in %s: %w", claim.Namespace, err)
|
||||
}
|
||||
for _, event := range events.Items {
|
||||
if strings.Contains(event.Message, "failed to create encrypted volume: the volume disappeared after creation, most likely due to inaccessible KMS encryption key") {
|
||||
@ -894,7 +894,7 @@ func waitForProvisionedVolumesDeleted(ctx context.Context, c clientset.Interface
|
||||
return true, nil // No PVs remain
|
||||
})
|
||||
if err != nil {
|
||||
return remainingPVs, fmt.Errorf("Error waiting for PVs to be deleted: %v", err)
|
||||
return remainingPVs, fmt.Errorf("Error waiting for PVs to be deleted: %w", err)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -782,7 +782,7 @@ func invokeVCenterServiceControl(ctx context.Context, command, service, host str
|
||||
result, err := e2essh.SSH(ctx, sshCmd, host, framework.TestContext.Provider)
|
||||
if err != nil || result.Code != 0 {
|
||||
e2essh.LogResult(result)
|
||||
return fmt.Errorf("couldn't execute command: %s on vCenter host: %v", sshCmd, err)
|
||||
return fmt.Errorf("couldn't execute command: %s on vCenter host: %w", sshCmd, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ func restartKubelet(ctx context.Context, host string) error {
|
||||
result, err := e2essh.SSH(ctx, cmd, host, framework.TestContext.Provider)
|
||||
if err != nil || result.Code != 0 {
|
||||
e2essh.LogResult(result)
|
||||
return fmt.Errorf("couldn't restart kubelet: %v", err)
|
||||
return fmt.Errorf("couldn't restart kubelet: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -49,22 +49,22 @@ func gatherTestSuiteMetrics(ctx context.Context) error {
|
||||
framework.Logf("Gathering metrics")
|
||||
config, err := framework.LoadConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading client config: %v", err)
|
||||
return fmt.Errorf("error loading client config: %w", err)
|
||||
}
|
||||
c, err := clientset.NewForConfig(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating client: %v", err)
|
||||
return fmt.Errorf("error creating client: %w", err)
|
||||
}
|
||||
|
||||
// Grab metrics for apiserver, scheduler, controller-manager, kubelet (for non-kubemark case) and cluster autoscaler (optionally).
|
||||
grabber, err := e2emetrics.NewMetricsGrabber(ctx, c, nil, config, !framework.ProviderIs("kubemark"), true, true, true, framework.TestContext.IncludeClusterAutoscalerMetrics, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create MetricsGrabber: %v", err)
|
||||
return fmt.Errorf("failed to create MetricsGrabber: %w", err)
|
||||
}
|
||||
|
||||
received, err := grabber.Grab(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to grab metrics: %v", err)
|
||||
return fmt.Errorf("failed to grab metrics: %w", err)
|
||||
}
|
||||
|
||||
metricsForE2E := (*e2emetrics.ComponentCollection)(&received)
|
||||
@ -72,7 +72,7 @@ func gatherTestSuiteMetrics(ctx context.Context) error {
|
||||
if framework.TestContext.ReportDir != "" {
|
||||
filePath := path.Join(framework.TestContext.ReportDir, "MetricsForE2ESuite_"+time.Now().Format(time.RFC3339)+".json")
|
||||
if err := os.WriteFile(filePath, []byte(metricsJSON), 0644); err != nil {
|
||||
return fmt.Errorf("error writing to %q: %v", filePath, err)
|
||||
return fmt.Errorf("error writing to %q: %w", filePath, err)
|
||||
}
|
||||
} else {
|
||||
framework.Logf("\n\nTest Suite Metrics:\n%s\n", metricsJSON)
|
||||
|
@ -184,7 +184,7 @@ func waitForDeploymentRevision(ctx context.Context, c clientset.Interface, d *ap
|
||||
return revision == targetRevision, nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error waiting for revision to become %q for deployment %q: %v", targetRevision, d.Name, err)
|
||||
return fmt.Errorf("error waiting for revision to become %q for deployment %q: %w", targetRevision, d.Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ func inClusterClientMustWork(ctx context.Context, f *framework.Framework, pod *v
|
||||
numTokens, err := e2eauth.ParseInClusterClientLogs(logs)
|
||||
if err != nil {
|
||||
framework.Logf("Error parsing inclusterclient logs: %v", err)
|
||||
return false, fmt.Errorf("inclusterclient reported an error: %v", err)
|
||||
return false, fmt.Errorf("inclusterclient reported an error: %w", err)
|
||||
}
|
||||
if numTokens == 0 {
|
||||
framework.Logf("No authenticated API calls found")
|
||||
|
@ -143,7 +143,7 @@ func waitForKubeProxyStaticPodsRunning(ctx context.Context, c clientset.Interfac
|
||||
}
|
||||
|
||||
if err := wait.PollImmediate(5*time.Second, defaultTestTimeout, condition); err != nil {
|
||||
return fmt.Errorf("error waiting for kube-proxy static pods running: %v", err)
|
||||
return fmt.Errorf("error waiting for kube-proxy static pods running: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -166,7 +166,7 @@ func waitForKubeProxyStaticPodsDisappear(ctx context.Context, c clientset.Interf
|
||||
}
|
||||
|
||||
if err := wait.PollImmediate(5*time.Second, defaultTestTimeout, condition); err != nil {
|
||||
return fmt.Errorf("error waiting for kube-proxy static pods disappear: %v", err)
|
||||
return fmt.Errorf("error waiting for kube-proxy static pods disappear: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -190,7 +190,7 @@ func waitForKubeProxyDaemonSetRunning(ctx context.Context, f *framework.Framewor
|
||||
}
|
||||
|
||||
if err := wait.PollImmediate(5*time.Second, defaultTestTimeout, condition); err != nil {
|
||||
return fmt.Errorf("error waiting for kube-proxy DaemonSet running: %v", err)
|
||||
return fmt.Errorf("error waiting for kube-proxy DaemonSet running: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -213,7 +213,7 @@ func waitForKubeProxyDaemonSetDisappear(ctx context.Context, c clientset.Interfa
|
||||
}
|
||||
|
||||
if err := wait.PollImmediate(5*time.Second, defaultTestTimeout, condition); err != nil {
|
||||
return fmt.Errorf("error waiting for kube-proxy DaemonSet disappear: %v", err)
|
||||
return fmt.Errorf("error waiting for kube-proxy DaemonSet disappear: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user