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  }