Skip to content

Commit e88d5c3

Browse files
committed
DRA resource claim controller: add statistics
This is primarily for testing. Proper metrics might be useful, but can still be added later.
1 parent d94752e commit e88d5c3

File tree

2 files changed

+83
-3
lines changed

2 files changed

+83
-3
lines changed

staging/src/k8s.io/dynamic-resource-allocation/resourceslice/resourceslicecontroller.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"errors"
2222
"fmt"
2323
"sync"
24+
"sync/atomic"
2425
"time"
2526

2627
"github.com/google/go-cmp/cmp"
@@ -66,6 +67,11 @@ type Controller struct {
6667
queue workqueue.TypedRateLimitingInterface[string]
6768
sliceStore cache.Indexer
6869

70+
// Must use atomic access...
71+
numCreates int64
72+
numUpdates int64
73+
numDeletes int64
74+
6975
mutex sync.RWMutex
7076

7177
// When receiving updates from the driver, the entire pointer replaced,
@@ -209,6 +215,25 @@ func (c *Controller) Update(resources *DriverResources) {
209215
}
210216
}
211217

218+
// GetStats provides some insights into operations of the controller.
219+
func (c *Controller) GetStats() Stats {
220+
s := Stats{
221+
NumCreates: atomic.LoadInt64(&c.numCreates),
222+
NumUpdates: atomic.LoadInt64(&c.numUpdates),
223+
NumDeletes: atomic.LoadInt64(&c.numDeletes),
224+
}
225+
return s
226+
}
227+
228+
type Stats struct {
229+
// NumCreates counts the number of ResourceSlices that got created.
230+
NumCreates int64
231+
// NumUpdates counts the number of ResourceSlices that got update.
232+
NumUpdates int64
233+
// NumDeletes counts the number of ResourceSlices that got deleted.
234+
NumDeletes int64
235+
}
236+
212237
// newController creates a new controller.
213238
func newController(ctx context.Context, options Options) (*Controller, error) {
214239
if options.KubeClient == nil {
@@ -540,6 +565,7 @@ func (c *Controller) syncPool(ctx context.Context, poolName string) error {
540565
if _, err := c.kubeClient.ResourceV1alpha3().ResourceSlices().Update(ctx, slice, metav1.UpdateOptions{}); err != nil {
541566
return fmt.Errorf("update resource slice: %w", err)
542567
}
568+
atomic.AddInt64(&c.numUpdates, 1)
543569
}
544570

545571
// Create new slices.
@@ -596,6 +622,7 @@ func (c *Controller) syncPool(ctx context.Context, poolName string) error {
596622
if _, err := c.kubeClient.ResourceV1alpha3().ResourceSlices().Create(ctx, slice, metav1.CreateOptions{}); err != nil {
597623
return fmt.Errorf("create resource slice: %w", err)
598624
}
625+
atomic.AddInt64(&c.numCreates, 1)
599626
}
600627
} else if len(slices) > 0 {
601628
// All are obsolete, pool does not exist anymore.
@@ -620,7 +647,13 @@ func (c *Controller) syncPool(ctx context.Context, poolName string) error {
620647
// changes on the server. The only downside is the extra API
621648
// call. This isn't as bad as extra creates.
622649
logger.V(5).Info("Deleting obsolete resource slice", "slice", klog.KObj(slice), "deleteOptions", options)
623-
if err := c.kubeClient.ResourceV1alpha3().ResourceSlices().Delete(ctx, slice.Name, options); err != nil && !apierrors.IsNotFound(err) {
650+
err := c.kubeClient.ResourceV1alpha3().ResourceSlices().Delete(ctx, slice.Name, options)
651+
switch {
652+
case err == nil:
653+
atomic.AddInt64(&c.numDeletes, 1)
654+
case apierrors.IsNotFound(err):
655+
// okay
656+
default:
624657
return fmt.Errorf("delete resource slice: %w", err)
625658
}
626659
}

staging/src/k8s.io/dynamic-resource-allocation/resourceslice/resourceslicecontroller_test.go

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ func TestControllerSyncPool(t *testing.T) {
9696
initialOtherObjects []runtime.Object
9797
inputDriverResources *DriverResources
9898
expectedResourceSlices []resourceapi.ResourceSlice
99+
expectedStats Stats
99100
}{
100101
"create-slice": {
101102
nodeUID: nodeUID,
@@ -107,6 +108,9 @@ func TestControllerSyncPool(t *testing.T) {
107108
},
108109
},
109110
},
111+
expectedStats: Stats{
112+
NumCreates: 1,
113+
},
110114
expectedResourceSlices: []resourceapi.ResourceSlice{
111115
*MakeResourceSlice().Name(generatedName1).GenerateName(generateName).
112116
NodeOwnerReferences(ownerName, string(nodeUID)).NodeName(ownerName).
@@ -145,7 +149,10 @@ func TestControllerSyncPool(t *testing.T) {
145149
Driver(driverName).Devices([]resourceapi.Device{}).
146150
Pool(resourceapi.ResourcePool{Name: poolName, Generation: 1, ResourceSliceCount: 1}).Obj(),
147151
},
148-
inputDriverResources: &DriverResources{},
152+
inputDriverResources: &DriverResources{},
153+
expectedStats: Stats{
154+
NumDeletes: 1,
155+
},
149156
expectedResourceSlices: nil,
150157
},
151158
"delete-and-add-slice": {
@@ -163,6 +170,10 @@ func TestControllerSyncPool(t *testing.T) {
163170
Slices: []Slice{{Devices: []resourceapi.Device{{Name: deviceName}}}}},
164171
},
165172
},
173+
expectedStats: Stats{
174+
NumDeletes: 1,
175+
NumCreates: 1,
176+
},
166177
expectedResourceSlices: []resourceapi.ResourceSlice{
167178
*MakeResourceSlice().Name(generatedName1).GenerateName(generateName).
168179
NodeOwnerReferences(ownerName, string(nodeUID)).NodeName(ownerName).
@@ -188,6 +199,9 @@ func TestControllerSyncPool(t *testing.T) {
188199
Slices: []Slice{{Devices: []resourceapi.Device{{Name: deviceName}}}}},
189200
},
190201
},
202+
expectedStats: Stats{
203+
NumDeletes: 1,
204+
},
191205
expectedResourceSlices: []resourceapi.ResourceSlice{
192206
*MakeResourceSlice().Name(resourceSlice1).UID(resourceSlice1).
193207
NodeOwnerReferences(ownerName, string(nodeUID)).NodeName(ownerName).
@@ -215,6 +229,9 @@ func TestControllerSyncPool(t *testing.T) {
215229
},
216230
},
217231
},
232+
expectedStats: Stats{
233+
NumUpdates: 1,
234+
},
218235
expectedResourceSlices: []resourceapi.ResourceSlice{
219236
*MakeResourceSlice().Name(resourceSlice1).UID(resourceSlice1).ResourceVersion("1").
220237
NodeOwnerReferences(ownerName, string(nodeUID)).NodeName(ownerName).
@@ -248,6 +265,9 @@ func TestControllerSyncPool(t *testing.T) {
248265
},
249266
},
250267
},
268+
expectedStats: Stats{
269+
NumUpdates: 1,
270+
},
251271
expectedResourceSlices: []resourceapi.ResourceSlice{
252272
*MakeResourceSlice().Name(resourceSlice1).UID(resourceSlice1).ResourceVersion("1").
253273
NodeOwnerReferences(ownerName, string(nodeUID)).NodeName(ownerName).
@@ -334,6 +354,9 @@ func TestControllerSyncPool(t *testing.T) {
334354
},
335355
},
336356
},
357+
expectedStats: Stats{
358+
NumDeletes: 2,
359+
},
337360
expectedResourceSlices: []resourceapi.ResourceSlice{
338361
*MakeResourceSlice().Name(resourceSlice2).UID(resourceSlice2).
339362
NodeOwnerReferences(ownerName, string(nodeUID)).NodeName(ownerName).
@@ -369,6 +392,9 @@ func TestControllerSyncPool(t *testing.T) {
369392
},
370393
},
371394
// Generation not bumped, only one update.
395+
expectedStats: Stats{
396+
NumUpdates: 1,
397+
},
372398
expectedResourceSlices: []resourceapi.ResourceSlice{
373399
*MakeResourceSlice().Name(resourceSlice1).UID(resourceSlice1).
374400
NodeOwnerReferences(ownerName, string(nodeUID)).NodeName(ownerName).
@@ -412,6 +438,9 @@ func TestControllerSyncPool(t *testing.T) {
412438
},
413439
},
414440
// Generation bumped, all updated.
441+
expectedStats: Stats{
442+
NumUpdates: 3,
443+
},
415444
expectedResourceSlices: []resourceapi.ResourceSlice{
416445
*MakeResourceSlice().Name(resourceSlice1).UID(resourceSlice1).
417446
NodeOwnerReferences(ownerName, string(nodeUID)).NodeName(ownerName).ResourceVersion("1").
@@ -454,6 +483,10 @@ func TestControllerSyncPool(t *testing.T) {
454483
},
455484
},
456485
// Generation bumped, two updated, one removed.
486+
expectedStats: Stats{
487+
NumUpdates: 2,
488+
NumDeletes: 1,
489+
},
457490
expectedResourceSlices: []resourceapi.ResourceSlice{
458491
*MakeResourceSlice().Name(resourceSlice1).UID(resourceSlice1).
459492
NodeOwnerReferences(ownerName, string(nodeUID)).NodeName(ownerName).ResourceVersion("1").
@@ -493,7 +526,10 @@ func TestControllerSyncPool(t *testing.T) {
493526
},
494527
},
495528
},
496-
// Three updated, one generated.
529+
expectedStats: Stats{
530+
NumUpdates: 3,
531+
NumCreates: 1,
532+
},
497533
expectedResourceSlices: []resourceapi.ResourceSlice{
498534
*MakeResourceSlice().Name(resourceSlice1).UID(resourceSlice1).ResourceVersion("1").
499535
NodeOwnerReferences(ownerName, string(nodeUID)).NodeName(ownerName).
@@ -523,6 +559,9 @@ func TestControllerSyncPool(t *testing.T) {
523559
},
524560
},
525561
},
562+
expectedStats: Stats{
563+
NumCreates: 1,
564+
},
526565
expectedResourceSlices: []resourceapi.ResourceSlice{
527566
*MakeResourceSlice().Name(driverName + "-0").GenerateName(driverName + "-").
528567
AllNodes(true).
@@ -540,6 +579,9 @@ func TestControllerSyncPool(t *testing.T) {
540579
},
541580
},
542581
},
582+
expectedStats: Stats{
583+
NumCreates: 1,
584+
},
543585
expectedResourceSlices: []resourceapi.ResourceSlice{
544586
*MakeResourceSlice().Name(generatedName1).GenerateName(generateName).
545587
AppOwnerReferences(ownerName).NodeSelector(nodeSelector).
@@ -562,6 +604,9 @@ func TestControllerSyncPool(t *testing.T) {
562604
},
563605
},
564606
},
607+
expectedStats: Stats{
608+
NumUpdates: 1,
609+
},
565610
expectedResourceSlices: []resourceapi.ResourceSlice{
566611
*MakeResourceSlice().Name(resourceSlice1).UID(resourceSlice1).ResourceVersion("1").
567612
AppOwnerReferences(ownerName).NodeSelector(otherNodeSelector).
@@ -626,6 +671,8 @@ func TestControllerSyncPool(t *testing.T) {
626671
sortResourceSlices(resourceSlices.Items)
627672
assert.Equal(t, test.expectedResourceSlices, resourceSlices.Items)
628673

674+
assert.Equal(t, test.expectedStats, ctrl.GetStats())
675+
629676
// The informer might have added a work item after ctrl.run returned.
630677
state := queue.State()
631678
state.Ready = nil

0 commit comments

Comments
 (0)