From fda3bdbd5ee461798fd3d958b30b45df1984da20 Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Wed, 14 Jan 2026 20:52:25 +0100 Subject: [PATCH] DRA tests: stop using deprecated ktesting functions Some of them were already converted previously, but didn't take full advantage of the more flexible methods: errors can be checked again by Gomega. --- test/e2e/dra/utils/builder.go | 16 +++---- test/e2e/dra/utils/deploy.go | 4 +- test/e2e_dra/coredra_test.go | 6 +-- test/e2e_dra/upgradedowngrade_test.go | 2 +- .../dra/binding_conditions_test.go | 24 ++++------- test/integration/dra/dra_test.go | 42 +++++++------------ test/integration/dra/helpers_test.go | 9 ++-- .../dra/resourceslicecontroller.go | 12 +++--- test/utils/localupcluster/localupcluster.go | 12 +++--- 9 files changed, 49 insertions(+), 78 deletions(-) diff --git a/test/e2e/dra/utils/builder.go b/test/e2e/dra/utils/builder.go index b5c2c7f3a5f..330c298786e 100644 --- a/test/e2e/dra/utils/builder.go +++ b/test/e2e/dra/utils/builder.go @@ -522,10 +522,8 @@ func (b *Builder) tearDown(tCtx ktesting.TContext) { tCtx.ExpectNoError(err, "delete pod") } } - ktesting.Eventually(tCtx, func(tCtx ktesting.TContext) []v1.Pod { - pods, err := b.listTestPods(tCtx) - tCtx.ExpectNoError(err) - return pods + tCtx.Eventually(func(tCtx ktesting.TContext) ([]v1.Pod, error) { + return b.listTestPods(tCtx) }).WithTimeout(time.Minute).Should(gomega.BeEmpty(), "remaining pods despite deletion") claims, err := b.ClientV1(tCtx).ResourceClaims(b.namespace).List(tCtx, metav1.ListOptions{}) @@ -543,15 +541,13 @@ func (b *Builder) tearDown(tCtx ktesting.TContext) { for host, plugin := range b.driver.Nodes { tCtx.Logf("Waiting for resources on %s to be unprepared", host) - ktesting.Eventually(tCtx, func(ktesting.TContext) []app.ClaimID { return plugin.GetPreparedResources() }).WithTimeout(time.Minute).Should(gomega.BeEmpty(), "prepared claims on host %s", host) + tCtx.Eventually(func(ktesting.TContext) []app.ClaimID { return plugin.GetPreparedResources() }).WithTimeout(time.Minute).Should(gomega.BeEmpty(), "prepared claims on host %s", host) } tCtx.Log("waiting for claims to be deallocated and deleted") - ktesting.Eventually(tCtx, func(tCtx ktesting.TContext) []resourceapi.ResourceClaim { - claims, err := client.ResourceClaims(tCtx.Namespace()).List(tCtx, metav1.ListOptions{}) - tCtx.ExpectNoError(err) - return claims.Items - }).WithTimeout(time.Minute).Should(gomega.BeEmpty(), "claims in the namespaces") + tCtx.Eventually(func(tCtx ktesting.TContext) (*resourceapi.ResourceClaimList, error) { + return client.ResourceClaims(tCtx.Namespace()).List(tCtx, metav1.ListOptions{}) + }).WithTimeout(time.Minute).Should(gomega.HaveField("Items", gomega.BeEmpty()), "claims in the namespaces") } func (b *Builder) listTestPods(tCtx ktesting.TContext) ([]v1.Pod, error) { diff --git a/test/e2e/dra/utils/deploy.go b/test/e2e/dra/utils/deploy.go index 776cced2efc..d0da49c7bd0 100644 --- a/test/e2e/dra/utils/deploy.go +++ b/test/e2e/dra/utils/deploy.go @@ -664,7 +664,7 @@ func (d *Driver) SetUp(tCtx ktesting.TContext, kubeletRootDir string, nodes *Nod // Wait for registration. tCtx.Log("wait for plugin registration") - ktesting.Eventually(tCtx, func(tCtx ktesting.TContext) map[string][]app.GRPCCall { + tCtx.Eventually(func(tCtx ktesting.TContext) map[string][]app.GRPCCall { notRegistered := make(map[string][]app.GRPCCall) for nodename, plugin := range d.Nodes { calls := plugin.GetGRPCCalls() @@ -995,7 +995,7 @@ func (d *Driver) TearDown(tCtx ktesting.TContext) { // Only use this in tests where kubelet support for DRA is guaranteed. func (d *Driver) IsGone(tCtx ktesting.TContext) { tCtx.Logf("Waiting for ResourceSlices of driver %s to be removed...", d.Name) - ktesting.Eventually(tCtx, d.NewGetSlices()).WithTimeout(2 * time.Minute).Should(gomega.HaveField("Items", gomega.BeEmpty())) + tCtx.Eventually(d.NewGetSlices()).WithTimeout(2 * time.Minute).Should(gomega.HaveField("Items", gomega.BeEmpty())) } func (d *Driver) interceptor(nodename string, ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { diff --git a/test/e2e_dra/coredra_test.go b/test/e2e_dra/coredra_test.go index 336c3dd200b..293014a03bf 100644 --- a/test/e2e_dra/coredra_test.go +++ b/test/e2e_dra/coredra_test.go @@ -56,13 +56,13 @@ func coreDRA(tCtx ktesting.TContext, b *drautils.Builder) upgradedTestFunc { // to the restarted apiserver. Sometimes, attempts fail with "EOF" as error // or (even weirder) with // getting *v1.Pod: pods "tester-2" is forbidden: User "kubernetes-admin" cannot get resource "pods" in API group "" in the namespace "dra-9021" - ktesting.Eventually(tCtx, func(tCtx ktesting.TContext) error { + tCtx.Eventually(func(tCtx ktesting.TContext) error { return tCtx.Client().ResourceV1beta1().ResourceClaims(namespace).Delete(tCtx, claim.Name, metav1.DeleteOptions{}) }).Should(gomega.Succeed(), "delete claim after downgrade") - ktesting.Eventually(tCtx, func(tCtx ktesting.TContext) error { + tCtx.Eventually(func(tCtx ktesting.TContext) error { return tCtx.Client().CoreV1().Pods(namespace).Delete(tCtx, pod.Name, metav1.DeleteOptions{}) }).Should(gomega.Succeed(), "delete pod after downgrade") - ktesting.Eventually(tCtx, func(tCtx ktesting.TContext) *v1.Pod { + tCtx.Eventually(func(tCtx ktesting.TContext) *v1.Pod { pod, err := tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) if apierrors.IsNotFound(err) { return nil diff --git a/test/e2e_dra/upgradedowngrade_test.go b/test/e2e_dra/upgradedowngrade_test.go index d3f8318d4c3..b53c06090f5 100644 --- a/test/e2e_dra/upgradedowngrade_test.go +++ b/test/e2e_dra/upgradedowngrade_test.go @@ -255,7 +255,7 @@ func testUpgradeDowngrade(tCtx ktesting.TContext) { // The kubelet wipes all ResourceSlices on a restart because it doesn't know which drivers were running. // Wait for the ResourceSlice controller in the driver to notice and recreate the ResourceSlices. - ktesting.Eventually(tCtx.WithStep("wait for ResourceSlices"), driver.NewGetSlices()).WithTimeout(5 * time.Minute).Should(gomega.HaveField("Items", gomega.HaveLen(len(nodes.NodeNames)))) + tCtx.WithStep("wait for ResourceSlices").Eventually(driver.NewGetSlices()).WithTimeout(5 * time.Minute).Should(gomega.HaveField("Items", gomega.HaveLen(len(nodes.NodeNames)))) downgradedTestFuncs := make(map[string]downgradedTestFunc, len(subTests)) tCtx.Run("after-cluster-upgrade", func(tCtx ktesting.TContext) { diff --git a/test/integration/dra/binding_conditions_test.go b/test/integration/dra/binding_conditions_test.go index c114b7cf70f..d37bf875231 100644 --- a/test/integration/dra/binding_conditions_test.go +++ b/test/integration/dra/binding_conditions_test.go @@ -444,10 +444,8 @@ profiles: // The scheduler should hit the binding timeout and surface that on the pod. // We poll the pod's conditions until we see a message containing "binding timeout". - tCtx.Eventually(func(tCtx ktesting.TContext) *v1.Pod { - p, err := tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) - tCtx.ExpectNoError(err, "get pod") - return p + tCtx.Eventually(func(tCtx ktesting.TContext) (*v1.Pod, error) { + return tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) }).WithTimeout(maxTO).WithPolling(300*time.Millisecond).Should( gomega.HaveField("Status.Conditions", gomega.ContainElement( @@ -465,10 +463,8 @@ profiles: "bindingTimeout should trigger roughly near %s (observed %v)", wantTO, elapsed, ) // Verify that the pod remains unscheduled after the binding timeout. - tCtx.Eventually(func(tCtx ktesting.TContext) *v1.Pod { - pod, err := tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) - tCtx.ExpectNoError(err, "get pod") - return pod + tCtx.Eventually(func(tCtx ktesting.TContext) (*v1.Pod, error) { + return tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) }).WithTimeout(wantTO).WithPolling(200 * time.Millisecond).Should(gomega.SatisfyAll( gomega.HaveField("Spec.NodeName", gomega.BeEmpty()), @@ -570,10 +566,8 @@ profiles: gomega.Succeed(), "slice must be created before binding timeout") // Wait until the binding timeout occurs. - tCtx.Eventually(func(tCtx ktesting.TContext) *v1.Pod { - p, err := tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) - tCtx.ExpectNoError(err, "get pod") - return p + tCtx.Eventually(func(tCtx ktesting.TContext) (*v1.Pod, error) { + return tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) }).WithTimeout(20*time.Second).WithPolling(300*time.Millisecond).Should( gomega.HaveField("Status.Conditions", gomega.ContainElement( @@ -586,10 +580,8 @@ profiles: ) // Verify recovery to the newly added device without BindingConditions through rescheduling triggered by binding timeout. - tCtx.Eventually(func(tCtx ktesting.TContext) *resourceapi.ResourceClaim { - c, err := tCtx.Client().ResourceV1().ResourceClaims(namespace).Get(tCtx, claim1.Name, metav1.GetOptions{}) - tCtx.ExpectNoError(err) - return c + tCtx.Eventually(func(tCtx ktesting.TContext) (*resourceapi.ResourceClaim, error) { + return tCtx.Client().ResourceV1().ResourceClaims(namespace).Get(tCtx, claim1.Name, metav1.GetOptions{}) }).WithTimeout(10*time.Second).WithPolling(1*time.Second).Should(gomega.HaveField( "Status.Allocation", gstruct.PointTo(gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{ diff --git a/test/integration/dra/dra_test.go b/test/integration/dra/dra_test.go index b129ff045f4..347006d70df 100644 --- a/test/integration/dra/dra_test.go +++ b/test/integration/dra/dra_test.go @@ -618,10 +618,8 @@ func testPrioritizedList(tCtx ktesting.TContext, enabled bool) { "Message": gomega.Equal("0/8 nodes are available: 8 cannot allocate all claims. still not schedulable, preemption: 0/8 nodes are available: 8 Preemption is not helpful for scheduling."), }), )) - tCtx.Eventually(func(tCtx ktesting.TContext) *v1.Pod { - pod, err := tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) - tCtx.ExpectNoError(err, "get pod") - return pod + tCtx.Eventually(func(tCtx ktesting.TContext) (*v1.Pod, error) { + return tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) }).WithTimeout(10 * time.Second).WithPolling(time.Second).Should(schedulingAttempted) } @@ -689,10 +687,8 @@ func testPrioritizedListScoring(tCtx ktesting.TContext) { _ = createPod(tCtx, namespace, "-pl-single-claim", podWithClaimName, claim) expectedSelectedRequest := fmt.Sprintf("%s/%s", claim.Spec.Devices.Requests[0].Name, claim.Spec.Devices.Requests[0].FirstAvailable[0].Name) - tCtx.Eventually(func(tCtx ktesting.TContext) *resourceapi.ResourceClaim { - c, err := tCtx.Client().ResourceV1().ResourceClaims(namespace).Get(tCtx, claim.Name, metav1.GetOptions{}) - tCtx.ExpectNoError(err) - return c + tCtx.Eventually(func(tCtx ktesting.TContext) (*resourceapi.ResourceClaim, error) { + return tCtx.Client().ResourceV1().ResourceClaims(namespace).Get(tCtx, claim.Name, metav1.GetOptions{}) }).WithTimeout(10 * time.Second).WithPolling(time.Second).Should(expectedAllocatedClaim(expectedSelectedRequest, nodeInfos[0])) }) @@ -751,18 +747,14 @@ func testPrioritizedListScoring(tCtx ktesting.TContext) { // The second subrequest in claim1 is for nodeInfos[2], so it should be chosen. expectedSelectedRequest := fmt.Sprintf("%s/%s", claim1.Spec.Devices.Requests[0].Name, claim1.Spec.Devices.Requests[0].FirstAvailable[1].Name) - tCtx.Eventually(func(tCtx ktesting.TContext) *resourceapi.ResourceClaim { - c, err := tCtx.Client().ResourceV1().ResourceClaims(namespace).Get(tCtx, claimPrioritizedList1.Name, metav1.GetOptions{}) - tCtx.ExpectNoError(err) - return c + tCtx.Eventually(func(tCtx ktesting.TContext) (*resourceapi.ResourceClaim, error) { + return tCtx.Client().ResourceV1().ResourceClaims(namespace).Get(tCtx, claimPrioritizedList1.Name, metav1.GetOptions{}) }).WithTimeout(10 * time.Second).WithPolling(time.Second).Should(expectedAllocatedClaim(expectedSelectedRequest, nodeInfos[2])) // The first subrequest in claim2 is for nodeInfos[2], so it should be chosen. expectedSelectedRequest = fmt.Sprintf("%s/%s", claim2.Spec.Devices.Requests[0].Name, claim2.Spec.Devices.Requests[0].FirstAvailable[0].Name) - tCtx.Eventually(func(tCtx ktesting.TContext) *resourceapi.ResourceClaim { - c, err := tCtx.Client().ResourceV1().ResourceClaims(namespace).Get(tCtx, claimPrioritizedList2.Name, metav1.GetOptions{}) - tCtx.ExpectNoError(err) - return c + tCtx.Eventually(func(tCtx ktesting.TContext) (*resourceapi.ResourceClaim, error) { + return tCtx.Client().ResourceV1().ResourceClaims(namespace).Get(tCtx, claimPrioritizedList2.Name, metav1.GetOptions{}) }).WithTimeout(10 * time.Second).WithPolling(time.Second).Should(expectedAllocatedClaim(expectedSelectedRequest, nodeInfos[2])) }) } @@ -833,10 +825,8 @@ func testExtendedResource(tCtx ktesting.TContext, enabled bool) { }), )) } - tCtx.Eventually(func(tCtx ktesting.TContext) *v1.Pod { - pod, err := tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) - tCtx.ExpectNoError(err, "get pod") - return pod + tCtx.Eventually(func(tCtx ktesting.TContext) (*v1.Pod, error) { + return tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) }).WithTimeout(time.Minute).WithPolling(time.Second).Should(schedulingAttempted) }) } @@ -1716,18 +1706,14 @@ func testInvalidResourceSlices(tCtx ktesting.TContext) { schedulingAttempted := gomega.HaveField("Status.Conditions", gomega.ContainElement( gstruct.MatchFields(gstruct.IgnoreExtras, tc.expectedPodScheduledCondition), )) - tCtx.Eventually(func(tCtx ktesting.TContext) *v1.Pod { - pod, err := tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) - tCtx.ExpectNoError(err, "get pod") - return pod + tCtx.Eventually(func(tCtx ktesting.TContext) (*v1.Pod, error) { + return tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, pod.Name, metav1.GetOptions{}) }).WithTimeout(10 * time.Second).WithPolling(time.Second).Should(schedulingAttempted) // Only check the ResourceClaim if we expected the Pod to schedule. if tc.expectPodToSchedule { - tCtx.Eventually(func(tCtx ktesting.TContext) *resourceapi.ResourceClaim { - c, err := tCtx.Client().ResourceV1().ResourceClaims(namespace).Get(tCtx, claim.Name, metav1.GetOptions{}) - tCtx.ExpectNoError(err) - return c + tCtx.Eventually(func(tCtx ktesting.TContext) (*resourceapi.ResourceClaim, error) { + return tCtx.Client().ResourceV1().ResourceClaims(namespace).Get(tCtx, claim.Name, metav1.GetOptions{}) }).WithTimeout(10 * time.Second).WithPolling(time.Second).Should(gomega.HaveField("Status.Allocation", gstruct.PointTo(gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{ "Devices": gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{ "Results": gomega.HaveExactElements(gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{ diff --git a/test/integration/dra/helpers_test.go b/test/integration/dra/helpers_test.go index e80b1fc2619..d83689851e5 100644 --- a/test/integration/dra/helpers_test.go +++ b/test/integration/dra/helpers_test.go @@ -165,8 +165,8 @@ func createPod(tCtx ktesting.TContext, namespace string, suffix string, pod *v1. func waitForPodScheduled(tCtx ktesting.TContext, namespace, podName string) { tCtx.Helper() - tCtx.Eventually(func(tCtx ktesting.TContext) *v1.Pod { - return must(tCtx, tCtx.Client().CoreV1().Pods(namespace).Get, podName, metav1.GetOptions{}) + tCtx.Eventually(func(tCtx ktesting.TContext) (*v1.Pod, error) { + return tCtx.Client().CoreV1().Pods(namespace).Get(tCtx, podName, metav1.GetOptions{}) }).WithTimeout(60*time.Second).Should( gomega.HaveField("Status.Conditions", gomega.ContainElement( gomega.And( @@ -207,11 +207,10 @@ func waitForNotFound[T any](tCtx ktesting.TContext, get func(context.Context, st func waitForClaim(tCtx ktesting.TContext, namespace, claimName string, timeout time.Duration, match gtypes.GomegaMatcher, description ...any) *resourceapi.ResourceClaim { tCtx.Helper() var latestClaim *resourceapi.ResourceClaim - tCtx.Eventually(func(tCtx ktesting.TContext) *resourceapi.ResourceClaim { + tCtx.Eventually(func(tCtx ktesting.TContext) (*resourceapi.ResourceClaim, error) { c, err := tCtx.Client().ResourceV1().ResourceClaims(namespace).Get(tCtx, claimName, metav1.GetOptions{}) - tCtx.ExpectNoError(err, "get claim") latestClaim = c - return latestClaim + return c, err }).WithTimeout(timeout).WithPolling(time.Second).Should(match, description...) return latestClaim } diff --git a/test/integration/dra/resourceslicecontroller.go b/test/integration/dra/resourceslicecontroller.go index 3a49d98e895..892b8784c8f 100644 --- a/test/integration/dra/resourceslicecontroller.go +++ b/test/integration/dra/resourceslicecontroller.go @@ -87,7 +87,7 @@ func TestCreateResourceSlices(tCtx ktesting.TContext, numSlices int) { tCtx.ExpectNoError(err, "start controller") tCtx.CleanupCtx(func(tCtx ktesting.TContext) { controller.Stop() - ktesting.Eventually(tCtx, func(tCtx ktesting.TContext) *resourceapi.ResourceSliceList { + tCtx.Eventually(func(tCtx ktesting.TContext) *resourceapi.ResourceSliceList { err := tCtx.Client().ResourceV1().ResourceSlices().DeleteCollection(tCtx, metav1.DeleteOptions{}, metav1.ListOptions{ FieldSelector: resourceapi.ResourceSliceSelectorDriver + "=" + driverName, }) @@ -97,7 +97,7 @@ func TestCreateResourceSlices(tCtx ktesting.TContext, numSlices int) { }) // Eventually we should have all desired slices. - ktesting.Eventually(tCtx, listSlices).WithTimeout(3 * time.Minute).Should(gomega.HaveField("Items", gomega.HaveLen(numSlices))) + tCtx.Eventually(listSlices).WithTimeout(3 * time.Minute).Should(gomega.HaveField("Items", gomega.HaveLen(numSlices))) // Verify state. expectSlices := listSlices(tCtx) @@ -110,7 +110,7 @@ func TestCreateResourceSlices(tCtx ktesting.TContext, numSlices int) { // No further changes expected now, after checking again. getStats := func(tCtx ktesting.TContext) resourceslice.Stats { return controller.GetStats() } - ktesting.Consistently(tCtx, getStats).WithTimeout(2 * mutationCacheTTL).Should(gomega.Equal(expectStats)) + tCtx.Consistently(getStats).WithTimeout(2 * mutationCacheTTL).Should(gomega.Equal(expectStats)) // Ask the controller to delete all slices except for one empty slice. tCtx.Log("Deleting slices") @@ -120,7 +120,7 @@ func TestCreateResourceSlices(tCtx ktesting.TContext, numSlices int) { // One empty slice should remain, after removing the full ones and adding the empty one. emptySlice := gomega.HaveField("Spec.Devices", gomega.BeEmpty()) - ktesting.Eventually(tCtx, listSlices).WithTimeout(2 * time.Minute).Should(gomega.HaveField("Items", gomega.HaveExactElements(emptySlice))) + tCtx.Eventually(listSlices).WithTimeout(2 * time.Minute).Should(gomega.HaveField("Items", gomega.HaveExactElements(emptySlice))) expectStats = resourceslice.Stats{NumCreates: int64(numSlices) + 1, NumDeletes: int64(numSlices)} // There is a window of time where the ResourceSlice exists and is @@ -128,7 +128,7 @@ func TestCreateResourceSlices(tCtx ktesting.TContext, numSlices int) { // in the controller's stats, consisting mostly of network latency // between this test process and the API server. Wait for the stats // to converge before asserting there are no further changes. - ktesting.Eventually(tCtx, getStats).WithTimeout(30 * time.Second).Should(gomega.Equal(expectStats)) + tCtx.Eventually(getStats).WithTimeout(30 * time.Second).Should(gomega.Equal(expectStats)) - ktesting.Consistently(tCtx, getStats).WithTimeout(2 * mutationCacheTTL).Should(gomega.Equal(expectStats)) + tCtx.Consistently(getStats).WithTimeout(2 * mutationCacheTTL).Should(gomega.Equal(expectStats)) } diff --git a/test/utils/localupcluster/localupcluster.go b/test/utils/localupcluster/localupcluster.go index e076b45a346..317b25515ea 100644 --- a/test/utils/localupcluster/localupcluster.go +++ b/test/utils/localupcluster/localupcluster.go @@ -472,20 +472,18 @@ func (c *Cluster) checkReadiness(tCtx ktesting.TContext, cmd *Cmd) { c.checkHealthz(tCtx, cmd, "https", c.settings["KUBELET_HOST"], c.settings["KUBELET_PORT"]) // Also wait for the node to be ready. - ktesting.Eventually(tCtx.WithStep("wait for node ready"), func(tCtx ktesting.TContext) []corev1.Node { - nodes, err := tCtx.Client().CoreV1().Nodes().List(tCtx, metav1.ListOptions{}) - tCtx.ExpectNoError(err, "list nodes") - return nodes.Items - }).Should(gomega.ConsistOf(gomega.HaveField("Status.Conditions", gomega.ContainElement(gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{ + tCtx.WithStep("wait for node ready").Eventually(func(tCtx ktesting.TContext) (*corev1.NodeList, error) { + return tCtx.Client().CoreV1().Nodes().List(tCtx, metav1.ListOptions{}) + }).Should(gomega.HaveField("Items", gomega.ConsistOf(gomega.HaveField("Status.Conditions", gomega.ContainElement(gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{ "Type": gomega.Equal(corev1.NodeReady), "Status": gomega.Equal(corev1.ConditionTrue), - }))))) + })))))) } } func (c *Cluster) checkHealthz(tCtx ktesting.TContext, cmd *Cmd, method, hostIP, port string) { url := fmt.Sprintf("%s://%s:%s/healthz", method, hostIP, port) - ktesting.Eventually(tCtx, func(tCtx ktesting.TContext) error { + tCtx.WithStep(fmt.Sprintf("check health %s", url)).Eventually(func(tCtx ktesting.TContext) error { if !cmd.Running() { return gomega.StopTrying(fmt.Sprintf("%s stopped unexpectedly", cmd.Name)) }