2 Copyright 2019 Intel Corporation.
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 http://www.apache.org/licenses/LICENSE-2.0
7 Unless required by applicable law or agreed to in writing, software
8 distributed under the License is distributed on an "AS IS" BASIS,
9 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 See the License for the specific language governing permissions and
11 limitations under the License.
24 "github.com/go-logr/logr"
26 onapv1alpha1 "collectd-operator/pkg/apis/onap/v1alpha1"
28 appsv1 "k8s.io/api/apps/v1"
29 corev1 "k8s.io/api/core/v1"
30 "k8s.io/apimachinery/pkg/api/errors"
31 "sigs.k8s.io/controller-runtime/pkg/client"
34 // Define the collectdPlugin finalizer for handling deletion
36 defaultWatchLabel = "app=collectd"
37 CollectdFinalizer = "finalizer.collectd.onap.org"
39 // WatchLabelsEnvVar is the constant for env variable WATCH_LABELS
40 // which is the labels where the watch activity happens.
41 // this value is empty if the operator is running with clusterScope.
42 WatchLabelsEnvVar = "WATCH_LABELS"
47 // ReconcileLock - Used to sync between global and plugin controller
48 var ReconcileLock sync.Mutex
50 // ResourceMap to hold objects to update/reload
51 type ResourceMap struct {
52 ConfigMap *corev1.ConfigMap
53 DaemonSet *appsv1.DaemonSet
54 CollectdPlugins *[]onapv1alpha1.CollectdPlugin
57 // ComputeSHA256 returns hash of data as string
58 func ComputeSHA256(data []byte) string {
59 hash := sha256.Sum256(data)
60 return fmt.Sprintf("%x", hash)
63 // Contains checks if a string is contained in a list of strings
64 func Contains(list []string, s string) bool {
65 for _, v := range list {
73 // Remove removes a string from a list of string
74 func Remove(list []string, s string) []string {
75 for i, v := range list {
77 list = append(list[:i], list[i+1:]...)
83 // GetWatchLabels returns the labels the operator should be watching for changes
84 func GetWatchLabels() (string, error) {
85 labelSelector, found := os.LookupEnv(WatchLabelsEnvVar)
87 return defaultWatchLabel, fmt.Errorf("%s must be set", WatchLabelsEnvVar)
89 return labelSelector, nil
92 // GetCollectdPluginList returns the list of CollectdPlugin instances in the namespace ns
93 func GetCollectdPluginList(rc client.Client, ns string) (*onapv1alpha1.CollectdPluginList, error) {
94 // Get all collectd plugins in the current namespace to rebuild conf.
95 collectdPlugins := &onapv1alpha1.CollectdPluginList{}
96 cpOpts := &client.ListOptions{}
97 cpOpts.InNamespace(ns)
98 err := rc.List(context.TODO(), cpOpts, collectdPlugins)
102 return collectdPlugins, nil
105 // GetConfigMap returns the GetConfigMap in the namespace ns
106 func GetConfigMap(rc client.Client, reqLogger logr.Logger, ns string) (*corev1.ConfigMap, error) {
110 reqLogger.Info("Get ConfigMap for collectd.conf")
111 // Get all collectd plugins in the current namespace to rebuild conf.
112 cmList := &corev1.ConfigMapList{}
113 opts := &client.ListOptions{}
114 // Select ConfigMaps with label
115 labelSelector, err := GetWatchLabels()
117 reqLogger.Error(err, "Failed to get watch labels, continuing with default label")
119 opts.SetLabelSelector(labelSelector)
122 err = rc.List(context.TODO(), opts, cmList)
127 if cmList.Items == nil || len(cmList.Items) == 0 {
128 return nil, errors.NewNotFound(corev1.Resource("configmap"), "ConfigMap")
131 cm := &cmList.Items[0]
135 // GetCollectdGlobal returns the CollectdGlobal instance in the namespace ns
136 func GetCollectdGlobal(rc client.Client, ns string) (*onapv1alpha1.CollectdGlobal, error) {
137 // Get the CollectdGlobal instance in current namespace to rebuild conf.
138 cgList := &onapv1alpha1.CollectdGlobalList{}
139 cpOpts := &client.ListOptions{}
140 cpOpts.InNamespace(ns)
141 err := rc.List(context.TODO(), cpOpts, cgList)
145 if cgList.Items == nil || len(cgList.Items) == 0 {
148 collectdGlobals := &cgList.Items[0]
149 return collectdGlobals, nil
152 // GetPodList returns the list of pods in the namespace ns
153 func GetPodList(rc client.Client, ns string) ([]string, error) {
155 podList := &corev1.PodList{}
156 opts := &client.ListOptions{}
157 // Select ConfigMaps with label
158 labelSelector, _ := GetWatchLabels()
159 opts.SetLabelSelector(labelSelector)
161 err := rc.List(context.TODO(), opts, podList)
166 if podList.Items == nil || len(podList.Items) == 0 {
170 for _, pod := range podList.Items {
171 pods = append(pods, pod.Name)
176 // RebuildCollectdConf Get all collectd plugins and reconstruct, compute Hash and check for changes
177 func RebuildCollectdConf(rc client.Client, ns string, isDelete bool, delPlugin string) (string, error) {
178 var collectdConf, collectdGlobalConf string
179 // Get the collectd global in the current namespace to rebuild conf.
180 cg, err := GetCollectdGlobal(rc, ns)
186 collectdGlobalConf += cg.Spec.GlobalOptions + "\n"
189 // Get all collectd plugins in the current namespace to rebuild conf.
190 cp, err := GetCollectdPluginList(rc, ns)
195 loadPlugin := make(map[string]string)
196 if *cpList != nil && len(*cpList) > 0 {
197 for _, cp := range *cpList {
198 // using CollectdPlugin to set global options. If CollectdGlobal CRD is defined do not check for this
199 if cp.Spec.PluginName == "global" {
201 collectdGlobalConf += cp.Spec.PluginConf + "\n"
204 loadPlugin[cp.Spec.PluginName] = cp.Spec.PluginConf
210 delete(loadPlugin, delPlugin)
212 collectdConf += collectdGlobalConf
215 pluginKeys := make([]string, 0, len(loadPlugin))
216 for k := range loadPlugin {
217 pluginKeys = append(pluginKeys, k)
219 sort.Strings(pluginKeys)
221 for _, cpName := range pluginKeys {
222 cpConf := loadPlugin[cpName]
223 collectdConf += "LoadPlugin" + " " + cpName + "\n"
224 collectdConf += cpConf + "\n"
227 collectdConf += "#Last line (collectd requires '\\n' at the last line)\n"
229 return collectdConf, nil