Collectd operator utilties
[demo.git] / vnfs / DAaaS / collectd-operator / pkg / controller / collectdplugin / collectdplugin_controller.go
1 package collectdplugin
2
3 import (
4         "context"
5         "crypto/sha256"
6
7         onapv1alpha1 "demo/vnfs/DAaaS/collectd-operator/pkg/apis/onap/v1alpha1"
8
9         corev1 "k8s.io/api/core/v1"
10         extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
11         "k8s.io/apimachinery/pkg/api/errors"
12         metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13         "k8s.io/apimachinery/pkg/runtime"
14         "sigs.k8s.io/controller-runtime/pkg/client"
15         "sigs.k8s.io/controller-runtime/pkg/controller"
16         "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
17         "sigs.k8s.io/controller-runtime/pkg/handler"
18         "sigs.k8s.io/controller-runtime/pkg/manager"
19         "sigs.k8s.io/controller-runtime/pkg/reconcile"
20         logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
21         "sigs.k8s.io/controller-runtime/pkg/source"
22 )
23
24 var log = logf.Log.WithName("controller_collectdplugin")
25
26 // ResourceMap to hold objects to update/reload
27 type ResourceMap struct {
28         configMap *corev1.ConfigMap
29         daemonSet *extensionsv1beta1.DaemonSet
30 }
31
32 /**
33 * USER ACTION REQUIRED: This is a scaffold file intended for the user to modify with their own Controller
34 * business logic.  Delete these comments after modifying this file.*
35  */
36
37 // Add creates a new CollectdPlugin Controller and adds it to the Manager. The Manager will set fields on the Controller
38 // and Start it when the Manager is Started.
39 func Add(mgr manager.Manager) error {
40         return add(mgr, newReconciler(mgr))
41 }
42
43 // newReconciler returns a new reconcile.Reconciler
44 func newReconciler(mgr manager.Manager) reconcile.Reconciler {
45         return &ReconcileCollectdPlugin{client: mgr.GetClient(), scheme: mgr.GetScheme()}
46 }
47
48 // add adds a new Controller to mgr with r as the reconcile.Reconciler
49 func add(mgr manager.Manager, r reconcile.Reconciler) error {
50         // Create a new controller
51         log.V(1).Info("Creating a new controller for CollectdPlugin")
52         c, err := controller.New("collectdplugin-controller", mgr, controller.Options{Reconciler: r})
53         if err != nil {
54                 return err
55         }
56
57         // Watch for changes to primary resource CollectdPlugin
58         log.V(1).Info("Add watcher for primary resource CollectdPlugin")
59         err = c.Watch(&source.Kind{Type: &onapv1alpha1.CollectdPlugin{}}, &handler.EnqueueRequestForObject{})
60         if err != nil {
61                 return err
62         }
63
64         // TODO(user): Modify this to be the types you create that are owned by the primary resource
65         // Watch for changes to secondary resource Pods and requeue the owner CollectdPlugin
66         log.V(1).Info("Add watcher for secondary resource ConfigMap")
67         err = c.Watch(&source.Kind{Type: &corev1.ConfigMap{}}, &handler.EnqueueRequestForOwner{
68                 IsController: true,
69                 OwnerType:    &onapv1alpha1.CollectdPlugin{},
70         })
71         if err != nil {
72                 return err
73         }
74
75         err = c.Watch(&source.Kind{Type: &extensionsv1beta1.DaemonSet{}}, &handler.EnqueueRequestForOwner{
76                 IsController: true,
77                 OwnerType:    &onapv1alpha1.CollectdPlugin{},
78         })
79         if err != nil {
80                 return err
81         }
82
83         return nil
84 }
85
86 // blank assignment to verify that ReconcileCollectdPlugin implements reconcile.Reconciler
87 var _ reconcile.Reconciler = &ReconcileCollectdPlugin{}
88
89 // ReconcileCollectdPlugin reconciles a CollectdPlugin object
90 type ReconcileCollectdPlugin struct {
91         // This client, initialized using mgr.Client() above, is a split client
92         // that reads objects from the cache and writes to the apiserver
93         client client.Client
94         scheme *runtime.Scheme
95 }
96
97 // Reconcile reads that state of the cluster for a CollectdPlugin object and makes changes based on the state read
98 // and what is in the CollectdPlugin.Spec
99 // TODO(user): Modify this Reconcile function to implement your Controller logic.  This example creates
100 // a Pod as an example
101 // Note:
102 // The Controller will requeue the Request to be processed again if the returned error is non-nil or
103 // Result.Requeue is true, otherwise upon completion it will remove the work from the queue.
104 func (r *ReconcileCollectdPlugin) Reconcile(request reconcile.Request) (reconcile.Result, error) {
105         reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
106         reqLogger.Info("Reconciling CollectdPlugin")
107
108         // Fetch the CollectdPlugin instance
109         instance := &onapv1alpha1.CollectdPlugin{}
110         err := r.client.Get(context.TODO(), request.NamespacedName, instance)
111         if err != nil {
112                 if errors.IsNotFound(err) {
113                         // Request object not found, could have been deleted after reconcile request.
114                         // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
115                         // Return and don't requeue
116                         reqLogger.V(1).Info("CollectdPlugin object Not found")
117                         return reconcile.Result{}, nil
118                 }
119                 // Error reading the object - requeue the request.
120                 reqLogger.V(1).Info("Error reading the CollectdPlugin object, Requeuing")
121                 return reconcile.Result{}, err
122         }
123
124         rmap, err := findResourceMapForCR(r, instance)
125         if err != nil {
126                 reqLogger.Info("Skip reconcile: ConfigMap not found")
127                 return reconcile.Result{}, err
128         }
129
130         cm := rmap.configMap
131         ds := rmap.daemonSet
132         reqLogger.V(1).Info("Found ResourceMap")
133         reqLogger.V(1).Info("ConfigMap.Namespace", cm.Namespace, "ConfigMap.Name", cm.Name)
134         reqLogger.V(1).Info("DaemonSet.Namespace", ds.Namespace, "DaemonSet.Name", ds.Name)
135         // Set CollectdPlugin instance as the owner and controller
136         if err := controllerutil.SetControllerReference(instance, cm, r.scheme); err != nil {
137                 return reconcile.Result{}, err
138         }
139         // Set CollectdConf instance as the owner and controller
140         if err := controllerutil.SetControllerReference(instance, ds, r.scheme); err != nil {
141                 return reconcile.Result{}, err
142         }
143
144         // Update the ConfigMap with new Spec and reload DaemonSets
145         reqLogger.Info("Updating the ConfigMap", "ConfigMap.Namespace", cm.Namespace, "ConfigMap.Name", cm.Name)
146         log.Info("Map: ", cm.Data)
147         err = r.client.Update(context.TODO(), cm)
148         if err != nil {
149                 return reconcile.Result{}, err
150         }
151
152         //Restart Collectd Pods
153
154         ds.Spec.Template.SetLabels(map[string]string{
155                 "daaas-random": ComputeSHA256([]byte("TEST")),
156         })
157         // Reconcile success
158         reqLogger.Info("Updated the ConfigMap", "ConfigMap.Namespace", cm.Namespace, "ConfigMap.Name", cm.Name)
159         return reconcile.Result{}, nil
160 }
161
162 // ComputeSHA256  returns hash of data as string
163 func ComputeSHA256(data []byte) string {
164         hash := sha256.Sum256(data)
165         return string(hash[:])
166 }
167
168 // findConfigMapForCR returns the configMap used by collectd Daemonset
169 func findResourceMapForCR(r *ReconcileCollectdPlugin, cr *onapv1alpha1.CollectdPlugin) (ResourceMap, error) {
170         cmList := &corev1.ConfigMapList{}
171         opts := &client.ListOptions{}
172         rmap := ResourceMap{}
173
174         // Select ConfigMaps with label app=collectd
175         opts.SetLabelSelector("app=collectd")
176         opts.InNamespace(cr.Namespace)
177         err := r.client.List(context.TODO(), opts, cmList)
178         if err != nil {
179                 return rmap, err
180         }
181
182         // Select DaemonSets with label app=collectd
183         dsList := &extensionsv1beta1.DaemonSet{}
184         err = r.client.List(context.TODO(), opts, dsList)
185         if err != nil {
186                 return rmap, err
187         }
188
189         rmap.configMap = &cmList.Items[0]
190         rmap.daemonSet = dsList
191         return rmap, err
192 }
193
194 // newPodForCR returns a busybox pod with the same name/namespace as the cr
195 func newPodForCR(cr *onapv1alpha1.CollectdPlugin) *corev1.Pod {
196         labels := map[string]string{
197                 "app": cr.Name,
198         }
199         return &corev1.Pod{
200                 ObjectMeta: metav1.ObjectMeta{
201                         Name:      cr.Name + "-pod",
202                         Namespace: cr.Namespace,
203                         Labels:    labels,
204                 },
205                 Spec: corev1.PodSpec{
206                         Containers: []corev1.Container{
207                                 {
208                                         Name:    "busybox",
209                                         Image:   "busybox",
210                                         Command: []string{"sleep", "3600"},
211                                 },
212                         },
213                 },
214         }
215 }