test(kube): WaitForDelete must return promptly for cluster-scoped objects

WaitForDelete watches with a namespace-scoped RESTScope strategy, so a
cluster-scoped resource never receives status events and stays Unknown.
In v4.2.1, 360d4835d deferred cancellation until a real status event
arrived, which made the delete-wait on such objects block for the full
timeout; pre-install hooks with cluster-scoped resources were never
created and installs sat in pending-install (#32224). The commit was
reverted in v4.2.2 (b05881cf9), and #32261 tracks re-attempting it.

This pins the required behaviour so any re-attempt cannot reintroduce
the hang: a delete-wait over a cluster-scoped object that receives no
events must complete promptly instead of waiting out the timeout.
Verified to fail against the reverted guard and pass on main.

Signed-off-by: Bisman-Singh <bismanmadaan1@gmail.com>
pull/32594/head
Bisman-Singh 2 weeks ago
parent d2de64e64b
commit b58c3ad1a3

@ -375,6 +375,47 @@ func TestStatusWaitForDeleteNonExistentObject(t *testing.T) {
assert.NoError(t, statusWaiter.WaitForDelete(resourceList, timeout)) assert.NoError(t, statusWaiter.WaitForDelete(resourceList, timeout))
} }
func TestStatusWaitForDeleteClusterScopedReturnsPromptly(t *testing.T) {
t.Parallel()
c := newTestClient(t)
// The timeout is deliberately generous: the regression this test guards
// against (#32224) made WaitForDelete block for the entire timeout, so
// completion well before this timeout is what separates correct behavior
// from the regression.
timeout := time.Second * 60
fakeClient := dynamicfake.NewSimpleDynamicClient(scheme.Scheme)
fakeMapper := testutil.NewFakeRESTMapper(
schema.GroupVersion{Group: "rbac.authorization.k8s.io", Version: "v1"}.WithKind("ClusterRole"),
)
statusWaiter := statusWaiter{
restMapper: fakeMapper,
client: fakeClient,
}
statusWaiter.SetLogger(slog.Default().Handler())
// The ClusterRole is intentionally never created. waitForDelete watches
// with RESTScopeNamespace, so a cluster-scoped resource can receive no
// status events and stay UnknownStatus for the entire wait. An
// Unknown-only set must aggregate to NotFound so the wait returns
// promptly. In v4.2.1, 360d4835d deferred cancellation until a real
// status event arrived, which made this scenario block for the full
// timeout; pre-install hooks with cluster-scoped resources were then
// never created (#32224). The commit was reverted in b05881cf9, and
// #32261 tracks re-attempting it without reintroducing this hang.
objManifest := getRuntimeObjFromManifests(t, []string{clusterRoleManifest})
resourceList := getResourceListFromRuntimeObjs(t, c, objManifest)
errCh := make(chan error, 1)
go func() {
errCh <- statusWaiter.WaitForDelete(resourceList, timeout)
}()
select {
case err := <-errCh:
assert.NoError(t, err)
case <-time.After(time.Second * 10):
t.Fatal("WaitForDelete blocked on a cluster-scoped resource that receives no status events; it must return promptly instead of waiting out the timeout")
}
}
func TestStatusWait(t *testing.T) { func TestStatusWait(t *testing.T) {
t.Parallel() t.Parallel()
tests := []struct { tests := []struct {

Loading…
Cancel
Save