github.com/netdata/go.d.plugin@v0.58.1/modules/k8s_state/kube_state.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package k8s_state
     4  
     5  import (
     6  	"context"
     7  	_ "embed"
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/netdata/go.d.plugin/agent/module"
    12  
    13  	"k8s.io/client-go/kubernetes"
    14  )
    15  
    16  //go:embed "config_schema.json"
    17  var configSchema string
    18  
    19  func init() {
    20  	module.Register("k8s_state", module.Creator{
    21  		JobConfigSchema: configSchema,
    22  		Defaults: module.Defaults{
    23  			Disabled: true,
    24  		},
    25  		Create: func() module.Module { return New() },
    26  	})
    27  }
    28  
    29  func New() *KubeState {
    30  	return &KubeState{
    31  		initDelay:     time.Second * 3,
    32  		newKubeClient: newKubeClient,
    33  		charts:        baseCharts.Copy(),
    34  		once:          &sync.Once{},
    35  		wg:            &sync.WaitGroup{},
    36  		state:         newKubeState(),
    37  	}
    38  }
    39  
    40  type (
    41  	discoverer interface {
    42  		run(ctx context.Context, in chan<- resource)
    43  		ready() bool
    44  		stopped() bool
    45  	}
    46  
    47  	KubeState struct {
    48  		module.Base
    49  
    50  		newKubeClient func() (kubernetes.Interface, error)
    51  
    52  		startTime time.Time
    53  		initDelay time.Duration
    54  
    55  		charts *module.Charts
    56  
    57  		client     kubernetes.Interface
    58  		once       *sync.Once
    59  		wg         *sync.WaitGroup
    60  		discoverer discoverer
    61  		ctx        context.Context
    62  		ctxCancel  context.CancelFunc
    63  		state      *kubeState
    64  
    65  		kubeClusterID   string
    66  		kubeClusterName string
    67  	}
    68  )
    69  
    70  func (ks *KubeState) Init() bool {
    71  	client, err := ks.initClient()
    72  	if err != nil {
    73  		ks.Errorf("client initialization: %v", err)
    74  		return false
    75  	}
    76  	ks.client = client
    77  
    78  	ks.ctx, ks.ctxCancel = context.WithCancel(context.Background())
    79  
    80  	ks.discoverer = ks.initDiscoverer(ks.client)
    81  
    82  	return true
    83  }
    84  
    85  func (ks *KubeState) Check() bool {
    86  	if ks.client == nil || ks.discoverer == nil {
    87  		ks.Error("not initialized job")
    88  		return false
    89  	}
    90  
    91  	ver, err := ks.client.Discovery().ServerVersion()
    92  	if err != nil {
    93  		ks.Errorf("failed to connect to the Kubernetes API server: %v", err)
    94  		return false
    95  	}
    96  
    97  	ks.Infof("successfully connected to the Kubernetes API server '%s'", ver)
    98  	return true
    99  }
   100  
   101  func (ks *KubeState) Charts() *module.Charts {
   102  	return ks.charts
   103  }
   104  
   105  func (ks *KubeState) Collect() map[string]int64 {
   106  	ms, err := ks.collect()
   107  	if err != nil {
   108  		ks.Error(err)
   109  	}
   110  
   111  	if len(ms) == 0 {
   112  		return nil
   113  	}
   114  	return ms
   115  }
   116  
   117  func (ks *KubeState) Cleanup() {
   118  	if ks.ctxCancel == nil {
   119  		return
   120  	}
   121  	ks.ctxCancel()
   122  
   123  	c := make(chan struct{})
   124  	go func() { defer close(c); ks.wg.Wait() }()
   125  
   126  	t := time.NewTimer(time.Second * 3)
   127  	defer t.Stop()
   128  
   129  	select {
   130  	case <-c:
   131  		return
   132  	case <-t.C:
   133  		return
   134  	}
   135  }