11 "github.com/go-logr/logr"
13 onapv1alpha1 "collectd-operator/pkg/apis/onap/v1alpha1"
15 appsv1 "k8s.io/api/apps/v1"
16 corev1 "k8s.io/api/core/v1"
17 "k8s.io/apimachinery/pkg/api/errors"
18 "sigs.k8s.io/controller-runtime/pkg/client"
21 // Define the collectdPlugin finalizer for handling deletion
23 defaultWatchLabel = "app=collectd"
24 CollectdFinalizer = "finalizer.collectd.onap.org"
26 // WatchLabelsEnvVar is the constant for env variable WATCH_LABELS
27 // which is the labels where the watch activity happens.
28 // this value is empty if the operator is running with clusterScope.
29 WatchLabelsEnvVar = "WATCH_LABELS"
34 // ReconcileLock - Used to sync between global and plugin controller
35 var ReconcileLock sync.Mutex
37 // ResourceMap to hold objects to update/reload
38 type ResourceMap struct {
39 ConfigMap *corev1.ConfigMap
40 DaemonSet *appsv1.DaemonSet
41 CollectdPlugins *[]onapv1alpha1.CollectdPlugin
44 // ComputeSHA256 returns hash of data as string
45 func ComputeSHA256(data []byte) string {
46 hash := sha256.Sum256(data)
47 return fmt.Sprintf("%x", hash)
50 // Contains checks if a string is contained in a list of strings
51 func Contains(list []string, s string) bool {
52 for _, v := range list {
60 // Remove removes a string from a list of string
61 func Remove(list []string, s string) []string {
62 for i, v := range list {
64 list = append(list[:i], list[i+1:]...)
70 // GetWatchLabels returns the labels the operator should be watching for changes
71 func GetWatchLabels() (string, error) {
72 labelSelector, found := os.LookupEnv(WatchLabelsEnvVar)
74 return defaultWatchLabel, fmt.Errorf("%s must be set", WatchLabelsEnvVar)
76 return labelSelector, nil
79 // GetCollectdPluginList returns the list of CollectdPlugin instances in the namespace ns
80 func GetCollectdPluginList(rc client.Client, ns string) (*onapv1alpha1.CollectdPluginList, error) {
81 // Get all collectd plugins in the current namespace to rebuild conf.
82 collectdPlugins := &onapv1alpha1.CollectdPluginList{}
83 cpOpts := &client.ListOptions{}
84 cpOpts.InNamespace(ns)
85 err := rc.List(context.TODO(), cpOpts, collectdPlugins)
89 return collectdPlugins, nil
92 // GetConfigMap returns the GetConfigMap in the namespace ns
93 func GetConfigMap(rc client.Client, reqLogger logr.Logger, ns string) (*corev1.ConfigMap, error) {
97 reqLogger.Info("Get ConfigMap for collectd.conf")
98 // Get all collectd plugins in the current namespace to rebuild conf.
99 cmList := &corev1.ConfigMapList{}
100 opts := &client.ListOptions{}
101 // Select ConfigMaps with label
102 labelSelector, err := GetWatchLabels()
104 reqLogger.Error(err, "Failed to get watch labels, continuing with default label")
106 opts.SetLabelSelector(labelSelector)
109 err = rc.List(context.TODO(), opts, cmList)
114 if cmList.Items == nil || len(cmList.Items) == 0 {
115 return nil, errors.NewNotFound(corev1.Resource("configmap"), "ConfigMap")
118 cm := &cmList.Items[0]
122 // GetCollectdGlobal returns the CollectdGlobal instance in the namespace ns
123 func GetCollectdGlobal(rc client.Client, ns string) (*onapv1alpha1.CollectdGlobal, error) {
124 // Get the CollectdGlobal instance in current namespace to rebuild conf.
125 cgList := &onapv1alpha1.CollectdGlobalList{}
126 cpOpts := &client.ListOptions{}
127 cpOpts.InNamespace(ns)
128 err := rc.List(context.TODO(), cpOpts, cgList)
132 if cgList.Items == nil || len(cgList.Items) == 0 {
135 collectdGlobals := &cgList.Items[0]
136 return collectdGlobals, nil
139 // GetPodList returns the list of pods in the namespace ns
140 func GetPodList(rc client.Client, ns string) ([]string, error) {
142 podList := &corev1.PodList{}
143 opts := &client.ListOptions{}
144 // Select ConfigMaps with label
145 labelSelector, _ := GetWatchLabels()
146 opts.SetLabelSelector(labelSelector)
148 err := rc.List(context.TODO(), opts, podList)
153 if podList.Items == nil || len(podList.Items) == 0 {
157 for _, pod := range podList.Items {
158 pods = append(pods, pod.Name)
163 // RebuildCollectdConf Get all collectd plugins and reconstruct, compute Hash and check for changes
164 func RebuildCollectdConf(rc client.Client, ns string, isDelete bool, delPlugin string) (string, error) {
165 var collectdConf, collectdGlobalConf string
166 // Get the collectd global in the current namespace to rebuild conf.
167 cg, err := GetCollectdGlobal(rc, ns)
173 collectdGlobalConf += cg.Spec.GlobalOptions + "\n"
176 // Get all collectd plugins in the current namespace to rebuild conf.
177 cp, err := GetCollectdPluginList(rc, ns)
182 loadPlugin := make(map[string]string)
183 if *cpList != nil && len(*cpList) > 0 {
184 for _, cp := range *cpList {
185 // using CollectdPlugin to set global options. If CollectdGlobal CRD is defined do not check for this
186 if cp.Spec.PluginName == "global" {
188 collectdGlobalConf += cp.Spec.PluginConf + "\n"
191 loadPlugin[cp.Spec.PluginName] = cp.Spec.PluginConf
197 delete(loadPlugin, delPlugin)
199 collectdConf += collectdGlobalConf
202 pluginKeys := make([]string, 0, len(loadPlugin))
203 for k := range loadPlugin {
204 pluginKeys = append(pluginKeys, k)
206 sort.Strings(pluginKeys)
208 for _, cpName := range pluginKeys {
209 cpConf := loadPlugin[cpName]
210 collectdConf += "LoadPlugin" + " " + cpName + "\n"
211 collectdConf += cpConf + "\n"
214 collectdConf += "#Last line (collectd requires '\\n' at the last line)\n"
216 return collectdConf, nil