@@ -19,6 +19,7 @@ package testing
19
19
import (
20
20
"fmt"
21
21
"reflect"
22
+ "sort"
22
23
"sync"
23
24
24
25
jsonpatch "github.com/evanphx/json-patch"
@@ -197,7 +198,7 @@ type tracker struct {
197
198
scheme ObjectScheme
198
199
decoder runtime.Decoder
199
200
lock sync.RWMutex
200
- objects map [schema.GroupVersionResource ][ ]runtime.Object
201
+ objects map [schema.GroupVersionResource ]map [types. NamespacedName ]runtime.Object
201
202
// The value type of watchers is a map of which the key is either a namespace or
202
203
// all/non namespace aka "" and its value is list of fake watchers.
203
204
// Manipulations on resources will broadcast the notification events into the
@@ -214,7 +215,7 @@ func NewObjectTracker(scheme ObjectScheme, decoder runtime.Decoder) ObjectTracke
214
215
return & tracker {
215
216
scheme : scheme ,
216
217
decoder : decoder ,
217
- objects : make (map [schema.GroupVersionResource ][ ]runtime.Object ),
218
+ objects : make (map [schema.GroupVersionResource ]map [types. NamespacedName ]runtime.Object ),
218
219
watchers : make (map [schema.GroupVersionResource ]map [string ][]* watch.RaceFreeFakeWatcher ),
219
220
}
220
221
}
@@ -282,31 +283,15 @@ func (t *tracker) Get(gvr schema.GroupVersionResource, ns, name string) (runtime
282
283
return nil , errNotFound
283
284
}
284
285
285
- var matchingObjs []runtime.Object
286
- for _ , obj := range objs {
287
- acc , err := meta .Accessor (obj )
288
- if err != nil {
289
- return nil , err
290
- }
291
- if acc .GetNamespace () != ns {
292
- continue
293
- }
294
- if acc .GetName () != name {
295
- continue
296
- }
297
- matchingObjs = append (matchingObjs , obj )
298
- }
299
- if len (matchingObjs ) == 0 {
286
+ matchingObj , ok := objs [types.NamespacedName {Namespace : ns , Name : name }]
287
+ if ! ok {
300
288
return nil , errNotFound
301
289
}
302
- if len (matchingObjs ) > 1 {
303
- return nil , fmt .Errorf ("more than one object matched gvr %s, ns: %q name: %q" , gvr , ns , name )
304
- }
305
290
306
291
// Only one object should match in the tracker if it works
307
292
// correctly, as Add/Update methods enforce kind/namespace/name
308
293
// uniqueness.
309
- obj := matchingObjs [ 0 ] .DeepCopyObject ()
294
+ obj := matchingObj .DeepCopyObject ()
310
295
if status , ok := obj .(* metav1.Status ); ok {
311
296
if status .Status != metav1 .StatusSuccess {
312
297
return nil , & errors.StatusError {ErrStatus : * status }
@@ -405,29 +390,29 @@ func (t *tracker) add(gvr schema.GroupVersionResource, obj runtime.Object, ns st
405
390
return errors .NewBadRequest (msg )
406
391
}
407
392
408
- for i , existingObj := range t .objects [gvr ] {
409
- oldMeta , err := meta .Accessor (existingObj )
410
- if err != nil {
411
- return err
412
- }
413
- if oldMeta .GetNamespace () == newMeta .GetNamespace () && oldMeta .GetName () == newMeta .GetName () {
414
- if replaceExisting {
415
- for _ , w := range t .getWatches (gvr , ns ) {
416
- w .Modify (obj )
417
- }
418
- t.objects [gvr ][i ] = obj
419
- return nil
393
+ _ , ok := t .objects [gvr ]
394
+ if ! ok {
395
+ t .objects [gvr ] = make (map [types.NamespacedName ]runtime.Object )
396
+ }
397
+
398
+ namespacedName := types.NamespacedName {Namespace : newMeta .GetNamespace (), Name : newMeta .GetName ()}
399
+ if _ , ok = t.objects [gvr ][namespacedName ]; ok {
400
+ if replaceExisting {
401
+ for _ , w := range t .getWatches (gvr , ns ) {
402
+ w .Modify (obj )
420
403
}
421
- return errors .NewAlreadyExists (gr , newMeta .GetName ())
404
+ t.objects [gvr ][namespacedName ] = obj
405
+ return nil
422
406
}
407
+ return errors .NewAlreadyExists (gr , newMeta .GetName ())
423
408
}
424
409
425
410
if replaceExisting {
426
411
// Tried to update but no matching object was found.
427
412
return errors .NewNotFound (gr , newMeta .GetName ())
428
413
}
429
414
430
- t .objects [gvr ] = append ( t . objects [ gvr ], obj )
415
+ t.objects [gvr ][ namespacedName ] = obj
431
416
432
417
for _ , w := range t .getWatches (gvr , ns ) {
433
418
w .Add (obj )
@@ -457,35 +442,28 @@ func (t *tracker) Delete(gvr schema.GroupVersionResource, ns, name string) error
457
442
t .lock .Lock ()
458
443
defer t .lock .Unlock ()
459
444
460
- found := false
461
-
462
- for i , existingObj := range t .objects [gvr ] {
463
- objMeta , err := meta .Accessor (existingObj )
464
- if err != nil {
465
- return err
466
- }
467
- if objMeta .GetNamespace () == ns && objMeta .GetName () == name {
468
- obj := t.objects [gvr ][i ]
469
- t .objects [gvr ] = append (t .objects [gvr ][:i ], t .objects [gvr ][i + 1 :]... )
470
- for _ , w := range t .getWatches (gvr , ns ) {
471
- w .Delete (obj )
472
- }
473
- found = true
474
- break
475
- }
445
+ objs , ok := t .objects [gvr ]
446
+ if ! ok {
447
+ return errors .NewNotFound (gvr .GroupResource (), name )
476
448
}
477
449
478
- if found {
479
- return nil
450
+ namespacedName := types.NamespacedName {Namespace : ns , Name : name }
451
+ obj , ok := objs [namespacedName ]
452
+ if ! ok {
453
+ return errors .NewNotFound (gvr .GroupResource (), name )
480
454
}
481
455
482
- return errors .NewNotFound (gvr .GroupResource (), name )
456
+ delete (objs , namespacedName )
457
+ for _ , w := range t .getWatches (gvr , ns ) {
458
+ w .Delete (obj )
459
+ }
460
+ return nil
483
461
}
484
462
485
463
// filterByNamespace returns all objects in the collection that
486
464
// match provided namespace. Empty namespace matches
487
465
// non-namespaced objects.
488
- func filterByNamespace (objs [ ]runtime.Object , ns string ) ([]runtime.Object , error ) {
466
+ func filterByNamespace (objs map [types. NamespacedName ]runtime.Object , ns string ) ([]runtime.Object , error ) {
489
467
var res []runtime.Object
490
468
491
469
for _ , obj := range objs {
@@ -499,6 +477,15 @@ func filterByNamespace(objs []runtime.Object, ns string) ([]runtime.Object, erro
499
477
res = append (res , obj )
500
478
}
501
479
480
+ // Sort res to get deterministic order.
481
+ sort .Slice (res , func (i , j int ) bool {
482
+ acc1 , _ := meta .Accessor (res [i ])
483
+ acc2 , _ := meta .Accessor (res [j ])
484
+ if acc1 .GetNamespace () != acc2 .GetNamespace () {
485
+ return acc1 .GetNamespace () < acc2 .GetNamespace ()
486
+ }
487
+ return acc1 .GetName () < acc2 .GetName ()
488
+ })
502
489
return res , nil
503
490
}
504
491
0 commit comments