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