Skip to content

Commit 484443f

Browse files
committed
chore(dra): refector controller to adapt the mock workqueue in unit test
1 parent 1c67ed0 commit 484443f

File tree

2 files changed

+92
-38
lines changed

2 files changed

+92
-38
lines changed

staging/src/k8s.io/dynamic-resource-allocation/controller/controller.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ func (ctrl *controller) Run(workers int) {
328328
}
329329

330330
for i := 0; i < workers; i++ {
331-
go wait.Until(ctrl.sync, 0, stopCh)
331+
go wait.Until(func() { ctrl.sync(ctrl.queue) }, 0, stopCh)
332332
}
333333

334334
<-stopCh
@@ -344,12 +344,12 @@ var errRequeue = errors.New("requeue")
344344
var errPeriodic = errors.New("periodic")
345345

346346
// sync is the main worker.
347-
func (ctrl *controller) sync() {
348-
key, quit := ctrl.queue.Get()
347+
func (ctrl *controller) sync(queue workqueue.TypedRateLimitingInterface[string]) {
348+
key, quit := queue.Get()
349349
if quit {
350350
return
351351
}
352-
defer ctrl.queue.Done(key)
352+
defer queue.Done(key)
353353

354354
logger := klog.LoggerWithValues(ctrl.logger, "key", key)
355355
ctx := klog.NewContext(ctrl.ctx, logger)
@@ -358,20 +358,20 @@ func (ctrl *controller) sync() {
358358
switch err {
359359
case nil:
360360
logger.V(5).Info("completed")
361-
ctrl.queue.Forget(key)
361+
queue.Forget(key)
362362
case errRequeue:
363363
logger.V(5).Info("requeue")
364-
ctrl.queue.AddRateLimited(key)
364+
queue.AddRateLimited(key)
365365
case errPeriodic:
366366
logger.V(5).Info("recheck periodically")
367-
ctrl.queue.AddAfter(key, recheckDelay)
367+
queue.AddAfter(key, recheckDelay)
368368
default:
369369
logger.Error(err, "processing failed")
370370
if obj != nil {
371371
// TODO: We don't know here *what* failed. Determine based on error?
372372
ctrl.eventRecorder.Event(obj, v1.EventTypeWarning, "Failed", err.Error())
373373
}
374-
ctrl.queue.AddRateLimited(key)
374+
queue.AddRateLimited(key)
375375
}
376376
}
377377

staging/src/k8s.io/dynamic-resource-allocation/controller/controller_test.go

Lines changed: 84 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"errors"
2222
"fmt"
2323
"testing"
24+
"time"
2425

2526
"github.com/stretchr/testify/assert"
2627
"github.com/stretchr/testify/require"
@@ -49,7 +50,7 @@ func TestController(t *testing.T) {
4950
claim := createClaim(claimName, claimNamespace, driverName)
5051
otherClaim := createClaim(claimName, claimNamespace, otherDriverName)
5152
podName := "pod"
52-
podKey := "schedulingCtx:default/pod"
53+
podSchedulingCtxKey := "schedulingCtx:default/pod"
5354
pod := createPod(podName, claimNamespace, nil)
5455
podClaimName := "my-pod-claim"
5556
podSchedulingCtx := createPodSchedulingContexts(pod)
@@ -125,11 +126,15 @@ func TestController(t *testing.T) {
125126
pod *corev1.Pod
126127
schedulingCtx, expectedSchedulingCtx *resourceapi.PodSchedulingContext
127128
claim, expectedClaim *resourceapi.ResourceClaim
128-
expectedError string
129+
expectedWorkQueueState Mock[string]
129130
}{
130131
"invalid-key": {
131-
key: "claim:x/y/z",
132-
expectedError: `unexpected key format: "x/y/z"`,
132+
key: "claim:x/y/z",
133+
expectedWorkQueueState: Mock[string]{
134+
Failures: map[string]int{
135+
"claim:x/y/z": 1,
136+
},
137+
},
133138
},
134139
"not-found": {
135140
key: "claim:default/claim",
@@ -154,7 +159,11 @@ func TestController(t *testing.T) {
154159
claim: withDeallocate(withAllocate(claim)),
155160
driver: m.expectDeallocate(map[string]error{claimName: errors.New("fake error")}),
156161
expectedClaim: withDeallocate(withAllocate(claim)),
157-
expectedError: "deallocate: fake error",
162+
expectedWorkQueueState: Mock[string]{
163+
Failures: map[string]int{
164+
claimKey: 1,
165+
},
166+
},
158167
},
159168

160169
// deletion time stamp set, our finalizer set, not allocated -> remove finalizer
@@ -170,7 +179,11 @@ func TestController(t *testing.T) {
170179
claim: withFinalizer(withDeletionTimestamp(claim), ourFinalizer),
171180
driver: m.expectDeallocate(map[string]error{claimName: errors.New("fake error")}),
172181
expectedClaim: withFinalizer(withDeletionTimestamp(claim), ourFinalizer),
173-
expectedError: "stop allocation: fake error",
182+
expectedWorkQueueState: Mock[string]{
183+
Failures: map[string]int{
184+
claimKey: 1,
185+
},
186+
},
174187
},
175188
// deletion time stamp set, other finalizer set, not allocated -> do nothing
176189
"deleted-finalizer-no-removal": {
@@ -191,7 +204,11 @@ func TestController(t *testing.T) {
191204
claim: withAllocate(withDeletionTimestamp(claim)),
192205
driver: m.expectDeallocate(map[string]error{claimName: errors.New("fake error")}),
193206
expectedClaim: withAllocate(withDeletionTimestamp(claim)),
194-
expectedError: "deallocate: fake error",
207+
expectedWorkQueueState: Mock[string]{
208+
Failures: map[string]int{
209+
claimKey: 1,
210+
},
211+
},
195212
},
196213
// deletion time stamp set, finalizer not set -> do nothing
197214
"deleted-no-finalizer": {
@@ -208,16 +225,23 @@ func TestController(t *testing.T) {
208225

209226
// pod with no claims -> shouldn't occur, check again anyway
210227
"pod-nop": {
211-
key: podKey,
228+
key: podSchedulingCtxKey,
212229
pod: pod,
213230
schedulingCtx: withSelectedNode(podSchedulingCtx),
214231
expectedSchedulingCtx: withSelectedNode(podSchedulingCtx),
215-
expectedError: errPeriodic.Error(),
232+
expectedWorkQueueState: Mock[string]{
233+
Later: []MockDelayedItem[string]{
234+
{
235+
Item: podSchedulingCtxKey,
236+
Duration: time.Second * 30,
237+
},
238+
},
239+
},
216240
},
217241

218242
// no potential nodes -> shouldn't occur
219243
"no-nodes": {
220-
key: podKey,
244+
key: podSchedulingCtxKey,
221245
claim: claim,
222246
expectedClaim: claim,
223247
pod: podWithClaim,
@@ -227,7 +251,7 @@ func TestController(t *testing.T) {
227251

228252
// potential nodes -> provide unsuitable nodes
229253
"info": {
230-
key: podKey,
254+
key: podSchedulingCtxKey,
231255
claim: claim,
232256
expectedClaim: claim,
233257
pod: podWithClaim,
@@ -236,12 +260,19 @@ func TestController(t *testing.T) {
236260
expectClaimParameters(map[string]interface{}{claimName: 2}).
237261
expectUnsuitableNodes(map[string][]string{podClaimName: unsuitableNodes}, nil),
238262
expectedSchedulingCtx: withUnsuitableNodes(withPotentialNodes(podSchedulingCtx)),
239-
expectedError: errPeriodic.Error(),
263+
expectedWorkQueueState: Mock[string]{
264+
Later: []MockDelayedItem[string]{
265+
{
266+
Item: podSchedulingCtxKey,
267+
Duration: time.Second * 30,
268+
},
269+
},
270+
},
240271
},
241272

242273
// potential nodes, selected node -> allocate
243274
"allocate": {
244-
key: podKey,
275+
key: podSchedulingCtxKey,
245276
claim: claim,
246277
expectedClaim: withReservedFor(withAllocate(claim), pod),
247278
pod: podWithClaim,
@@ -251,11 +282,18 @@ func TestController(t *testing.T) {
251282
expectUnsuitableNodes(map[string][]string{podClaimName: unsuitableNodes}, nil).
252283
expectAllocate(map[string]allocate{claimName: {allocResult: &allocation, selectedNode: nodeName, allocErr: nil}}),
253284
expectedSchedulingCtx: withUnsuitableNodes(withSelectedNode(withPotentialNodes(podSchedulingCtx))),
254-
expectedError: errPeriodic.Error(),
285+
expectedWorkQueueState: Mock[string]{
286+
Later: []MockDelayedItem[string]{
287+
{
288+
Item: "schedulingCtx:default/pod",
289+
Duration: time.Second * 30,
290+
},
291+
},
292+
},
255293
},
256294
// potential nodes, selected node, all unsuitable -> update unsuitable nodes
257295
"is-potential-node": {
258-
key: podKey,
296+
key: podSchedulingCtxKey,
259297
claim: claim,
260298
expectedClaim: claim,
261299
pod: podWithClaim,
@@ -264,11 +302,18 @@ func TestController(t *testing.T) {
264302
expectClaimParameters(map[string]interface{}{claimName: 2}).
265303
expectUnsuitableNodes(map[string][]string{podClaimName: potentialNodes}, nil),
266304
expectedSchedulingCtx: withSpecificUnsuitableNodes(withSelectedNode(withPotentialNodes(podSchedulingCtx)), potentialNodes),
267-
expectedError: errPeriodic.Error(),
305+
expectedWorkQueueState: Mock[string]{
306+
Later: []MockDelayedItem[string]{
307+
{
308+
Item: podSchedulingCtxKey,
309+
Duration: time.Second * 30,
310+
},
311+
},
312+
},
268313
},
269314
// max potential nodes, other selected node, all unsuitable -> update unsuitable nodes with truncation at start
270315
"is-potential-node-truncate-first": {
271-
key: podKey,
316+
key: podSchedulingCtxKey,
272317
claim: claim,
273318
expectedClaim: claim,
274319
pod: podWithClaim,
@@ -277,11 +322,18 @@ func TestController(t *testing.T) {
277322
expectClaimParameters(map[string]interface{}{claimName: 2}).
278323
expectUnsuitableNodes(map[string][]string{podClaimName: append(maxNodes, nodeName)}, nil),
279324
expectedSchedulingCtx: withSpecificUnsuitableNodes(withSelectedNode(withSpecificPotentialNodes(podSchedulingCtx, maxNodes)), append(maxNodes[1:], nodeName)),
280-
expectedError: errPeriodic.Error(),
325+
expectedWorkQueueState: Mock[string]{
326+
Later: []MockDelayedItem[string]{
327+
{
328+
Item: podSchedulingCtxKey,
329+
Duration: time.Second * 30,
330+
},
331+
},
332+
},
281333
},
282334
// max potential nodes, other selected node, all unsuitable (but in reverse order) -> update unsuitable nodes with truncation at end
283335
"pod-selected-is-potential-node-truncate-last": {
284-
key: podKey,
336+
key: podSchedulingCtxKey,
285337
claim: claim,
286338
expectedClaim: claim,
287339
pod: podWithClaim,
@@ -290,7 +342,14 @@ func TestController(t *testing.T) {
290342
expectClaimParameters(map[string]interface{}{claimName: 2}).
291343
expectUnsuitableNodes(map[string][]string{podClaimName: append([]string{nodeName}, maxNodes...)}, nil),
292344
expectedSchedulingCtx: withSpecificUnsuitableNodes(withSelectedNode(withSpecificPotentialNodes(podSchedulingCtx, maxNodes)), append([]string{nodeName}, maxNodes[:len(maxNodes)-1]...)),
293-
expectedError: errPeriodic.Error(),
345+
expectedWorkQueueState: Mock[string]{
346+
Later: []MockDelayedItem[string]{
347+
{
348+
Item: podSchedulingCtxKey,
349+
Duration: time.Second * 30,
350+
},
351+
},
352+
},
294353
},
295354
} {
296355
t.Run(name, func(t *testing.T) {
@@ -340,16 +399,11 @@ func TestController(t *testing.T) {
340399
) {
341400
t.Fatal("could not sync caches")
342401
}
343-
_, err := ctrl.(*controller).syncKey(ctx, test.key)
344-
if err != nil && test.expectedError == "" {
345-
t.Fatalf("unexpected error: %v", err)
346-
}
347-
if err == nil && test.expectedError != "" {
348-
t.Fatalf("did not get expected error %q", test.expectedError)
349-
}
350-
if err != nil && err.Error() != test.expectedError {
351-
t.Fatalf("expected error %q, got %q", test.expectedError, err.Error())
352-
}
402+
var workQueueState Mock[string]
403+
c := ctrl.(*controller)
404+
workQueueState.SyncOne(test.key, c.sync)
405+
assert.Equal(t, test.expectedWorkQueueState, workQueueState)
406+
353407
claims, err := kubeClient.ResourceV1alpha3().ResourceClaims("").List(ctx, metav1.ListOptions{})
354408
require.NoError(t, err, "list claims")
355409
var expectedClaims []resourceapi.ResourceClaim

0 commit comments

Comments
 (0)