Collectd Global CRD
[demo.git] / vnfs / DAaaS / microservices / collectd-operator / pkg / controller / utils / collectdutils.go
1 package utils
2
3 import (
4         "context"
5         "crypto/sha256"
6         "fmt"
7         "os"
8         "sync"
9
10         "github.com/go-logr/logr"
11
12         onapv1alpha1 "demo/vnfs/DAaaS/microservices/collectd-operator/pkg/apis/onap/v1alpha1"
13
14         corev1 "k8s.io/api/core/v1"
15         extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
16         "k8s.io/apimachinery/pkg/api/errors"
17         "sigs.k8s.io/controller-runtime/pkg/client"
18 )
19
20 // Define the collectdPlugin finalizer for handling deletion
21 const (
22         defaultWatchLabel       = "app=collectd"
23         CollectdFinalizer = "finalizer.collectd.onap.org"
24
25         // WatchLabelsEnvVar is the constant for env variable WATCH_LABELS
26         // which is the labels where the watch activity happens.
27         // this value is empty if the operator is running with clusterScope.
28         WatchLabelsEnvVar = "WATCH_LABELS"
29 )
30
31 var lock sync.Mutex
32
33 // ResourceMap to hold objects to update/reload
34 type ResourceMap struct {
35         ConfigMap       *corev1.ConfigMap
36         DaemonSet       *extensionsv1beta1.DaemonSet
37         CollectdPlugins *[]onapv1alpha1.CollectdPlugin
38 }
39
40 // ComputeSHA256  returns hash of data as string
41 func ComputeSHA256(data []byte) string {
42         hash := sha256.Sum256(data)
43         return fmt.Sprintf("%x", hash)
44 }
45
46 // Contains checks if a string is contained in a list of strings
47 func Contains(list []string, s string) bool {
48         for _, v := range list {
49                 if v == s {
50                         return true
51                 }
52         }
53         return false
54 }
55
56 // Remove removes a string from a list of string
57 func Remove(list []string, s string) []string {
58         for i, v := range list {
59                 if v == s {
60                         list = append(list[:i], list[i+1:]...)
61                 }
62         }
63         return list
64 }
65
66 // GetWatchLabels returns the labels the operator should be watching for changes
67 func GetWatchLabels() (string, error) {
68         labelSelector, found := os.LookupEnv(WatchLabelsEnvVar)
69         if !found {
70                 return defaultWatchLabel, fmt.Errorf("%s must be set", WatchLabelsEnvVar)
71         }
72         return labelSelector, nil
73 }
74
75 // FindResourceMapForCR returns the configMap, collectd Daemonset and list of Collectd Plugins
76 func FindResourceMapForCR(rc client.Client, reqLogger logr.Logger, ns string) (*ResourceMap, error) {
77         lock.Lock()
78         defer lock.Unlock()
79         cmList := &corev1.ConfigMapList{}
80         opts := &client.ListOptions{}
81         rmap := &ResourceMap{}
82
83         // Select ConfigMaps with label
84         labelSelector, err := GetWatchLabels()
85         if err != nil {
86                 reqLogger.Error(err, "Failed to get watch labels, continuing with default label")
87         }
88         opts.SetLabelSelector(labelSelector)
89         opts.InNamespace(ns)
90
91         err = rc.List(context.TODO(), opts, cmList)
92         if err != nil {
93                 return rmap, err
94         }
95
96         if cmList.Items == nil || len(cmList.Items) == 0 {
97                 return rmap, errors.NewNotFound(corev1.Resource("configmap"), "ConfigMap")
98         }
99
100         // Select DaemonSets with label
101         dsList := &extensionsv1beta1.DaemonSetList{}
102         err = rc.List(context.TODO(), opts, dsList)
103         if err != nil {
104                 return rmap, err
105         }
106
107         if dsList.Items == nil || len(dsList.Items) == 0 {
108                 return rmap, errors.NewNotFound(corev1.Resource("daemonset"), "DaemonSet")
109         }
110
111         rmap.ConfigMap = &cmList.Items[0]
112         rmap.DaemonSet = &dsList.Items[0]
113
114         return rmap, err
115 }
116
117 // GetCollectdPluginList returns the list of CollectdPlugin instances in the namespace ns
118 func GetCollectdPluginList(rc client.Client, ns string) (*onapv1alpha1.CollectdPluginList, error) {
119         // Get all collectd plugins in the current namespace to rebuild conf.
120         collectdPlugins := &onapv1alpha1.CollectdPluginList{}
121         cpOpts := &client.ListOptions{}
122         cpOpts.InNamespace(ns)
123         err := rc.List(context.TODO(), cpOpts, collectdPlugins)
124         if err != nil {
125                 return nil, err
126         }
127         return collectdPlugins, nil
128 }
129
130 // GetCollectdGlobal returns the CollectdGlobal instance in the namespace ns
131 func GetCollectdGlobal(rc client.Client, ns string) (*onapv1alpha1.CollectdGlobal, error) {
132         // Get the CollectdGlobal instance in current namespace to rebuild conf.
133         cgList := &onapv1alpha1.CollectdGlobalList{}
134         cpOpts := &client.ListOptions{}
135         cpOpts.InNamespace(ns)
136         err := rc.List(context.TODO(), cpOpts, cgList)
137         if err != nil {
138                 return nil, err
139         }
140         if cgList.Items == nil || len(cgList.Items) == 0 {
141                 return nil, err
142         }
143         collectdGlobals := &cgList.Items[0]
144         return collectdGlobals, nil
145 }
146
147 // GetPodList returns the list of pods in the namespace ns
148 func GetPodList(rc client.Client, ns string) ([]string, error) {
149         var pods []string
150         podList := &corev1.PodList{}
151         opts := &client.ListOptions{}
152         // Select ConfigMaps with label
153         labelSelector, _ := GetWatchLabels()
154         opts.SetLabelSelector(labelSelector)
155         opts.InNamespace(ns)
156         err := rc.List(context.TODO(), opts, podList)
157         if err != nil {
158                 return nil, err
159         }
160
161         if podList.Items == nil || len(podList.Items) == 0 {
162                 return nil, err
163         }
164
165         for _, pod := range podList.Items {
166                 pods = append(pods, pod.Name)
167         }
168         return pods, nil
169 }
170
171 // RebuildCollectdConf Get all collectd plugins and reconstruct, compute Hash and check for changes
172 func RebuildCollectdConf(rc client.Client, ns string, isDelete bool, delPlugin string) (string, error) {
173         var collectdConf, collectdGlobalConf string
174         // Get the collectd global in the current namespace to rebuild conf.
175         cg, err := GetCollectdGlobal(rc, ns)
176         if err != nil {
177                 return "", err
178         }
179
180         if cg != nil {
181                 collectdGlobalConf += cg.Spec.GlobalOptions + "\n"
182         }
183
184         // Get all collectd plugins in the current namespace to rebuild conf.
185         cp, err := GetCollectdPluginList(rc, ns)
186         if err != nil {
187                 return "", err
188         }
189         cpList := &cp.Items
190         loadPlugin := make(map[string]string)
191         if *cpList != nil && len(*cpList) > 0 {
192                 for _, cp := range *cpList {
193                         // using CollectdPlugin to set global options. If CollectdGlobal CRD is defined do not check for this
194                         if cp.Spec.PluginName == "global" {
195                                 if cg == nil {
196                                         collectdGlobalConf += cp.Spec.PluginConf + "\n"
197                                 }
198                         } else {
199                                 loadPlugin[cp.Spec.PluginName] = cp.Spec.PluginConf
200                         }
201                 }
202         }
203         
204         if isDelete {
205                 delete(loadPlugin, delPlugin)
206         } else {
207                 collectdConf += collectdGlobalConf
208         }
209
210         for cpName, cpConf := range loadPlugin {
211                 collectdConf += "LoadPlugin" + " " + cpName + "\n"
212                 collectdConf += cpConf + "\n"
213         }
214
215         collectdConf += "#Last line (collectd requires ā€˜\\nā€™ at the last line)\n"
216
217         return collectdConf, nil
218 }