What you would like to be added?
Create a dedicated e2e/waiter package that provides a single, generic WaitFor function driven by user-supplied predicates.
API sketch:
w := waiter.New(
waiter.WithTimeout(4 * time.Minute),
waiter.WithInterval(5 * time.Second),
waiter.WithLogger(logger),
)
// Generic WaitFor — caller supplies fetch + predicate
pods, err := waiter.WaitFor(ctx, w, func(ctx context.Context) (*v1.PodList, error) {
return clientset.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{})
}, func(pods *v1.PodList) bool {
return len(pods.Items) == expectedCount
})
The Waiter struct holds defaults (timeout, interval, logger). The WaitFor[T] function is generic — it takes a fetch function func(ctx) (T, error) and a predicate func(T) bool, polls until the predicate returns true, and returns the final T value. This replaces all specialized wait functions with one composable primitive.
Currently, wait/poll logic is scattered across multiple packages with inconsistent signatures:
- utils.WaitForPods, WaitForPodCount, WaitForPodCountAndPhases, WaitForPodsInNamespace, WaitForPodsWithClientset — 6 pod wait variants differing only in client type or condition checked
- utils.WaitForPodCliqueScalingGroup, WaitForPodClique, DeletePodCliqueSetAndWait — Grove resource waiters
- k8s.PollForCondition — low-level polling primitive
- k8s/pods.PodManager.WaitFor* — manager-level waiters that duplicate utils
- ~50 inline PollForCondition closures across test files for ad-hoc conditions
The new package should:
- Expose a Waiter struct configured via With... options (WithTimeout, WithInterval, WithLogger)
- Provide a single generic WaitFor[T](ctx, w, fetchFn, predicateFn) (T, error) as the core primitive
- Optionally provide common predicate helpers (e.g. CountEquals(n), AllRunning()) for readability
- Replace the current mix of free functions, manager methods, and inline poll closures
Why is this needed?
Every wait function today takes ctx, a client (sometimes restConfig, sometimes clientset, sometimes dynamicClient), namespace, timeout, and interval as individual arguments — 7-10 parameter signatures with easy-to-miss ordering bugs. The same condition (e.g. "N pods running") is implemented as both a dedicated function in utils and as inline closures in tests. A generic
predicate-based waiter eliminates all specialized variants: callers compose what they need from fetch + predicate. One place to add logging on timeout, backoff, or diagnostics. Tests become shorter and more expressive.
What you would like to be added?
Create a dedicated e2e/waiter package that provides a single, generic WaitFor function driven by user-supplied predicates.
API sketch:
w := waiter.New(
waiter.WithTimeout(4 * time.Minute),
waiter.WithInterval(5 * time.Second),
waiter.WithLogger(logger),
)
// Generic WaitFor — caller supplies fetch + predicate
pods, err := waiter.WaitFor(ctx, w, func(ctx context.Context) (*v1.PodList, error) {
return clientset.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{})
}, func(pods *v1.PodList) bool {
return len(pods.Items) == expectedCount
})
The Waiter struct holds defaults (timeout, interval, logger). The WaitFor[T] function is generic — it takes a fetch function func(ctx) (T, error) and a predicate func(T) bool, polls until the predicate returns true, and returns the final T value. This replaces all specialized wait functions with one composable primitive.
Currently, wait/poll logic is scattered across multiple packages with inconsistent signatures:
The new package should:
Why is this needed?
Every wait function today takes ctx, a client (sometimes restConfig, sometimes clientset, sometimes dynamicClient), namespace, timeout, and interval as individual arguments — 7-10 parameter signatures with easy-to-miss ordering bugs. The same condition (e.g. "N pods running") is implemented as both a dedicated function in utils and as inline closures in tests. A generic
predicate-based waiter eliminates all specialized variants: callers compose what they need from fetch + predicate. One place to add logging on timeout, backoff, or diagnostics. Tests become shorter and more expressive.