testutil.GetKey(d,t)funcGetKey(objinterface{},t*testing.T)string{// 每个删除的对象都是这个类型, 这里取出了真实的对象tombstone,ok:=obj.(cache.DeletedFinalStateUnknown)ifok{// if tombstone , try getting the value from tombstone.Objobj=tombstone.Obj}// 取出指针类型中 value,获取 Name 属性val:=reflect.ValueOf(obj).Elem()name:=val.FieldByName("Name").String()iflen(name)==0{t.Errorf("Unexpected object %v",obj)}// 获取key, 结果就是 {namespace}/{name}key,err:=keyFunc(obj)iferr!=nil{t.Errorf("Unexpected error getting key for %T %v: %v",val.Interface(),name,err)return""}returnkey}
func(t*tracker)Add(objruntime.Object)error{// 添加 Listifmeta.IsListType(obj){returnt.addList(obj,false)}// 用来获取 namespaceobjMeta,err:=meta.Accessor(obj)// 获取 gvkgvks,_,err:=t.scheme.ObjectKinds(obj)for_,gvk:=rangegvks{// NOTE: UnsafeGuessKindToResource is a heuristic and default match. The// actual registration in apiserver can specify arbitrary route for a// gvk. If a test uses such objects, it cannot preset the tracker with// objects via Add(). Instead, it should trigger the Create() function// of the tracker, where an arbitrary gvr can be specified.gvr,_:=meta.UnsafeGuessKindToResource(gvk)// Resource doesn't have the concept of "__internal" version, just set it to "".ifgvr.Version==runtime.APIVersionInternal{gvr.Version=""}// 添加这个err:=t.add(gvr,obj,objMeta.GetNamespace(),false)iferr!=nil{returnerr}}returnnil}
func(t*tracker)add(gvrschema.GroupVersionResource,objruntime.Object,nsstring,replaceExistingbool)error{t.lock.Lock()defert.lock.Unlock()gr:=gvr.GroupResource()// To avoid the object from being accidentally modified by caller// after it's been added to the tracker, we always store the deep// copy.obj=obj.DeepCopyObject()newMeta,err:=meta.Accessor(obj)_,ok:=t.objects[gvr]if!ok{t.objects[gvr]=make(map[types.NamespacedName]runtime.Object)}// replaceExisting 策略来放入新对象namespacedName:=types.NamespacedName{Namespace:newMeta.GetNamespace(),Name:newMeta.GetName()}if_,ok=t.objects[gvr][namespacedName];ok{ifreplaceExisting{for_,w:=ranget.getWatches(gvr,ns){// To avoid the object from being accidentally modified by watcher// 最终操作: f.result <- Event{Modified, obj}w.Modify(obj.DeepCopyObject())}// 覆盖原先的对象t.objects[gvr][namespacedName]=objreturnnil}returnerrors.NewAlreadyExists(gr,newMeta.GetName())}ifreplaceExisting{// Tried to update but no matching object was found.returnerrors.NewNotFound(gr,newMeta.GetName())}// 最终也就是放到这个 map 中t.objects[gvr][namespacedName]=obj// 实现 objectTracker, 每添加一个新的对象,就会向 chan 中放入这个新对象// 最终操作: f.result <- Event{Added, obj)for_,w:=ranget.getWatches(gvr,ns){// To avoid the object from being accidentally modified by watcherw.Add(obj.DeepCopyObject())}returnnil}