github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/cloud/pkg/edgecontroller/manager/pod.go (about) 1 package manager 2 3 import ( 4 "reflect" 5 "sync" 6 7 "k8s.io/api/core/v1" 8 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 "k8s.io/apimachinery/pkg/fields" 10 "k8s.io/apimachinery/pkg/watch" 11 "k8s.io/client-go/kubernetes" 12 "k8s.io/client-go/tools/cache" 13 "k8s.io/klog" 14 15 "github.com/kubeedge/kubeedge/cloud/pkg/edgecontroller/config" 16 ) 17 18 // CachePod is the struct save pod data for check pod is really changed 19 type CachePod struct { 20 metav1.ObjectMeta 21 Spec v1.PodSpec 22 } 23 24 // PodManager is a manager watch pod change event 25 type PodManager struct { 26 // events from watch kubernetes api server 27 realEvents chan watch.Event 28 29 // events merged 30 mergedEvents chan watch.Event 31 32 // pods, key is UID, value is *v1.Pod 33 pods sync.Map 34 } 35 36 func (pm *PodManager) isPodUpdated(old *CachePod, new *v1.Pod) bool { 37 // does not care fields 38 old.ObjectMeta.ResourceVersion = new.ObjectMeta.ResourceVersion 39 old.ObjectMeta.Generation = new.ObjectMeta.Generation 40 41 // return true if ObjectMeta or Spec changed, else false 42 return !reflect.DeepEqual(old.ObjectMeta, new.ObjectMeta) || !reflect.DeepEqual(old.Spec, new.Spec) 43 } 44 45 func (pm *PodManager) merge() { 46 for re := range pm.realEvents { 47 pod := re.Object.(*v1.Pod) 48 switch re.Type { 49 case watch.Added: 50 pm.pods.Store(pod.UID, &CachePod{ObjectMeta: pod.ObjectMeta, Spec: pod.Spec}) 51 if pod.DeletionTimestamp == nil { 52 pm.mergedEvents <- re 53 } else { 54 re.Type = watch.Modified 55 pm.mergedEvents <- re 56 } 57 case watch.Deleted: 58 pm.pods.Delete(pod.UID) 59 pm.mergedEvents <- re 60 case watch.Modified: 61 value, ok := pm.pods.Load(pod.UID) 62 pm.pods.Store(pod.UID, &CachePod{ObjectMeta: pod.ObjectMeta, Spec: pod.Spec}) 63 if ok { 64 cachedPod := value.(*CachePod) 65 if pm.isPodUpdated(cachedPod, pod) { 66 pm.mergedEvents <- re 67 } 68 } else { 69 pm.mergedEvents <- re 70 } 71 default: 72 klog.Warningf("event type: %s unsupported", re.Type) 73 } 74 } 75 } 76 77 // Events return a channel, can receive all pod event 78 func (pm *PodManager) Events() chan watch.Event { 79 return pm.mergedEvents 80 } 81 82 // NewPodManager create PodManager from config 83 func NewPodManager(kubeClient *kubernetes.Clientset, namespace, nodeName string) (*PodManager, error) { 84 var lw *cache.ListWatch 85 if "" == nodeName { 86 lw = cache.NewListWatchFromClient(kubeClient.CoreV1().RESTClient(), "pods", namespace, fields.Everything()) 87 } else { 88 selector := fields.OneTermEqualSelector("spec.nodeName", nodeName) 89 lw = cache.NewListWatchFromClient(kubeClient.CoreV1().RESTClient(), "pods", namespace, selector) 90 } 91 realEvents := make(chan watch.Event, config.Config.Buffer.PodEvent) 92 mergedEvents := make(chan watch.Event, config.Config.Buffer.PodEvent) 93 rh := NewCommonResourceEventHandler(realEvents) 94 si := cache.NewSharedInformer(lw, &v1.Pod{}, 0) 95 si.AddEventHandler(rh) 96 97 pm := &PodManager{realEvents: realEvents, mergedEvents: mergedEvents} 98 99 stopNever := make(chan struct{}) 100 go si.Run(stopNever) 101 go pm.merge() 102 103 return pm, nil 104 }