github.com/netdata/go.d.plugin@v0.58.1/modules/k8s_state/discover_pod.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package k8s_state 4 5 import ( 6 "context" 7 8 "github.com/netdata/go.d.plugin/logger" 9 10 "k8s.io/client-go/tools/cache" 11 "k8s.io/client-go/util/workqueue" 12 ) 13 14 func newPodDiscoverer(si cache.SharedInformer, l *logger.Logger) *podDiscoverer { 15 if si == nil { 16 panic("nil pod shared informer") 17 } 18 19 queue := workqueue.NewNamed("pod") 20 si.AddEventHandler(cache.ResourceEventHandlerFuncs{ 21 AddFunc: func(obj interface{}) { enqueue(queue, obj) }, 22 UpdateFunc: func(_, obj interface{}) { enqueue(queue, obj) }, 23 DeleteFunc: func(obj interface{}) { enqueue(queue, obj) }, 24 }) 25 26 return &podDiscoverer{ 27 Logger: l, 28 informer: si, 29 queue: queue, 30 readyCh: make(chan struct{}), 31 stopCh: make(chan struct{}), 32 } 33 } 34 35 type podResource struct { 36 src string 37 val interface{} 38 } 39 40 func (r podResource) source() string { return r.src } 41 func (r podResource) kind() kubeResourceKind { return kubeResourcePod } 42 func (r podResource) value() interface{} { return r.val } 43 44 type podDiscoverer struct { 45 *logger.Logger 46 informer cache.SharedInformer 47 queue *workqueue.Type 48 readyCh chan struct{} 49 stopCh chan struct{} 50 } 51 52 func (d *podDiscoverer) run(ctx context.Context, in chan<- resource) { 53 d.Info("pod_discoverer is started") 54 defer func() { close(d.stopCh); d.Info("pod_discoverer is stopped") }() 55 56 defer d.queue.ShutDown() 57 58 go d.informer.Run(ctx.Done()) 59 60 if !cache.WaitForCacheSync(ctx.Done(), d.informer.HasSynced) { 61 return 62 } 63 64 go d.runDiscover(ctx, in) 65 close(d.readyCh) 66 67 <-ctx.Done() 68 } 69 70 func (d *podDiscoverer) ready() bool { return isChanClosed(d.readyCh) } 71 func (d *podDiscoverer) stopped() bool { return isChanClosed(d.stopCh) } 72 73 func (d *podDiscoverer) runDiscover(ctx context.Context, in chan<- resource) { 74 for { 75 item, shutdown := d.queue.Get() 76 if shutdown { 77 return 78 } 79 80 func() { 81 defer d.queue.Done(item) 82 83 key := item.(string) 84 ns, name, err := cache.SplitMetaNamespaceKey(key) 85 if err != nil { 86 return 87 } 88 89 item, exists, err := d.informer.GetStore().GetByKey(key) 90 if err != nil { 91 return 92 } 93 94 r := &podResource{src: podSource(ns, name)} 95 if exists { 96 r.val = item 97 } 98 send(ctx, in, r) 99 }() 100 } 101 } 102 103 func podSource(namespace, name string) string { 104 return "k8s/pod/" + namespace + "/" + name 105 }