+// Get all collectd plugins and reconstruct, compute Hash and check for changes
+func rebuildCollectdConf(cr *onapv1alpha1.CollectdPlugin, cpList *[]onapv1alpha1.CollectdPlugin, isDelete bool) (string, error) {
+ var collectdConf string
+ if *cpList == nil || len(*cpList) == 0 {
+ return "", errors.NewNotFound(corev1.Resource("collectdplugin"), "CollectdPlugin")
+ }
+ loadPlugin := make(map[string]string)
+ for _, cp := range *cpList {
+ if cp.Spec.PluginName == "global" {
+ collectdConf += cp.Spec.PluginConf + "\n"
+ } else {
+ loadPlugin[cp.Spec.PluginName] = cp.Spec.PluginConf
+ }
+ }
+
+ if isDelete {
+ delete(loadPlugin, cr.Spec.PluginName)
+ }
+
+ log.V(1).Info("::::::: Plugins Map ::::::: ", "PluginMap ", loadPlugin)
+
+ for cpName, cpConf := range loadPlugin {
+ collectdConf += "LoadPlugin" + " " + cpName + "\n"
+ collectdConf += cpConf + "\n"
+ }
+
+ collectdConf += "#Last line (collectd requires ā\\nā at the last line)\n"
+
+ return collectdConf, nil
+}
+
+// Handle Delete CR event for additional cleanup
+func (r *ReconcileCollectdPlugin) handleDelete(reqLogger logr.Logger, cr *onapv1alpha1.CollectdPlugin) (bool, error) {
+ // Check if the CollectdPlugin instance is marked to be deleted, which is
+ // indicated by the deletion timestamp being set.
+ isMarkedToBeDeleted := cr.GetDeletionTimestamp() != nil
+ if isMarkedToBeDeleted {
+ // Update status to Deleting state
+ cr.Status.Status = onapv1alpha1.Deleting
+ cr.Status.CollectdAgents = nil
+ _ = r.client.Status().Update(context.TODO(), cr)
+
+ if contains(cr.GetFinalizers(), collectdPluginFinalizer) {
+ // Run finalization logic for collectdPluginFinalizer. If the
+ // finalization logic fails, don't remove the finalizer so
+ // that we can retry during the next reconciliation.
+ if err := r.finalizeCollectdPlugin(reqLogger, cr); err != nil {
+ return isMarkedToBeDeleted, err
+ }
+
+ // Remove collectdPluginFinalizer. Once all finalizers have been
+ // removed, the object will be deleted.
+ cr.SetFinalizers(remove(cr.GetFinalizers(), collectdPluginFinalizer))
+ err := r.client.Update(context.TODO(), cr)
+ if err != nil {
+ return isMarkedToBeDeleted, err
+ }
+ }
+ }
+ return isMarkedToBeDeleted, nil
+}
+
+func (r *ReconcileCollectdPlugin) updateStatus(cr *onapv1alpha1.CollectdPlugin) error {
+ switch cr.Status.Status {
+ case onapv1alpha1.Initial:
+ cr.Status.Status = onapv1alpha1.Created
+ case onapv1alpha1.Created, onapv1alpha1.Enabled:
+ pods, err := r.getPodList(cr.Namespace)
+ if err != nil {
+ return err
+ }
+ if !reflect.DeepEqual(pods, cr.Status.CollectdAgents) {
+ cr.Status.CollectdAgents = pods
+ cr.Status.Status = onapv1alpha1.Enabled
+ }
+ case onapv1alpha1.Deleting, onapv1alpha1.Deprecated:
+ return nil
+ }
+ err := r.client.Status().Update(context.TODO(), cr)
+ return err
+}
+
+func (r *ReconcileCollectdPlugin) finalizeCollectdPlugin(reqLogger logr.Logger, cr *onapv1alpha1.CollectdPlugin) error {
+ // Cleanup by regenerating new collectd conf and rolling update of DaemonSet
+ if err := r.handleCollectdPlugin(reqLogger, cr, true); err != nil {
+ reqLogger.Error(err, "Finalize CollectdPlugin failed!!")
+ return err
+ }
+ reqLogger.Info("Successfully finalized CollectdPlugin!!")
+ return nil
+}
+
+func (r *ReconcileCollectdPlugin) addFinalizer(reqLogger logr.Logger, cr *onapv1alpha1.CollectdPlugin) error {
+ reqLogger.Info("Adding Finalizer for the CollectdPlugin")
+ cr.SetFinalizers(append(cr.GetFinalizers(), collectdPluginFinalizer))
+ // Update status from Initial to Created
+ // Since addFinalizer will be executed only once,
+ // the status will be changed from Initial state to Created
+ updateErr := r.updateStatus(cr)
+ if updateErr != nil {
+ reqLogger.Error(updateErr, "Failed to update status from Initial state")
+ }
+ // Update CR
+ err := r.client.Update(context.TODO(), cr)
+ if err != nil {
+ reqLogger.Error(err, "Failed to update CollectdPlugin with finalizer")
+ return err
+ }
+ return nil
+}
+
+func contains(list []string, s string) bool {
+ for _, v := range list {
+ if v == s {
+ return true
+ }
+ }
+ return false
+}
+
+func remove(list []string, s string) []string {
+ for i, v := range list {
+ if v == s {
+ list = append(list[:i], list[i+1:]...)
+ }
+ }
+ return list
+}
+
+// getWatchLabels returns the labels the operator should be watching for changes
+func getWatchLabels() (string, error) {
+ labelSelector, found := os.LookupEnv(WatchLabelsEnvVar)
+ if !found {
+ return defaultWatchLabel, fmt.Errorf("%s must be set", WatchLabelsEnvVar)
+ }
+ return labelSelector, nil
+}
+
+func (r *ReconcileCollectdPlugin) getPodList(ns string) ([]string, error) {
+ var pods []string
+ podList := &corev1.PodList{}
+ opts := &client.ListOptions{}
+ // Select ConfigMaps with label
+ labelSelector, _ := getWatchLabels()
+ opts.SetLabelSelector(labelSelector)
+ opts.InNamespace(ns)
+ err := r.client.List(context.TODO(), opts, podList)
+ if err != nil {
+ return nil, err
+ }
+
+ if podList.Items == nil || len(podList.Items) == 0 {
+ return nil, err
+ }
+
+ for _, pod := range podList.Items {
+ pods = append(pods, pod.Name)
+ }
+ return pods, nil
+}
+
+func (r *ReconcileCollectdPlugin) getCollectdPluginList(ns string) (*onapv1alpha1.CollectdPluginList, error) {
+ // Get all collectd plugins in the current namespace to rebuild conf.
+ collectdPlugins := &onapv1alpha1.CollectdPluginList{}
+ cpOpts := &client.ListOptions{}
+ cpOpts.InNamespace(ns)
+ err := r.client.List(context.TODO(), cpOpts, collectdPlugins)
+ if err != nil {
+ return nil, err