visualization operator: Add datasource
[demo.git] / vnfs / DAaaS / microservices / visualization-operator / pkg / controller / grafanadatasource / grafanadatasource_controller.go
1 package grafanadatasource
2
3 import (
4         "bytes"
5         "context"
6         "encoding/json"
7
8         onapv1alpha1 "visualization-operator/pkg/apis/onap/v1alpha1"
9
10         "k8s.io/apimachinery/pkg/api/errors"
11         "k8s.io/apimachinery/pkg/runtime"
12         "net/http"
13         "sigs.k8s.io/controller-runtime/pkg/client"
14         "sigs.k8s.io/controller-runtime/pkg/controller"
15         "sigs.k8s.io/controller-runtime/pkg/handler"
16         "sigs.k8s.io/controller-runtime/pkg/manager"
17         "sigs.k8s.io/controller-runtime/pkg/reconcile"
18         logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
19         "sigs.k8s.io/controller-runtime/pkg/source"
20 )
21
22 var log = logf.Log.WithName("controller_grafanadatasource")
23
24 // Add creates a new GrafanaDataSource Controller and adds it to the Manager. The Manager will set fields on the Controller
25 // and Start it when the Manager is Started.
26 func Add(mgr manager.Manager) error {
27         return add(mgr, newReconciler(mgr))
28 }
29
30 // newReconciler returns a new reconcile.Reconciler
31 func newReconciler(mgr manager.Manager) reconcile.Reconciler {
32         return &ReconcileGrafanaDataSource{client: mgr.GetClient(), scheme: mgr.GetScheme()}
33 }
34
35 // add adds a new Controller to mgr with r as the reconcile.Reconciler
36 func add(mgr manager.Manager, r reconcile.Reconciler) error {
37         // Create a new controller
38         c, err := controller.New("grafanadatasource-controller", mgr, controller.Options{Reconciler: r})
39         if err != nil {
40                 return err
41         }
42
43         // Watch for changes to primary resource GrafanaDataSource
44         err = c.Watch(&source.Kind{Type: &onapv1alpha1.GrafanaDataSource{}}, &handler.EnqueueRequestForObject{})
45         if err != nil {
46                 return err
47         }
48
49         return nil
50 }
51
52 // blank assignment to verify that ReconcileGrafanaDataSource implements reconcile.Reconciler
53 var _ reconcile.Reconciler = &ReconcileGrafanaDataSource{}
54
55 // ReconcileGrafanaDataSource reconciles a GrafanaDataSource object
56 type ReconcileGrafanaDataSource struct {
57         // This client, initialized using mgr.Client() above, is a split client
58         // that reads objects from the cache and writes to the apiserver
59         client client.Client
60         scheme *runtime.Scheme
61 }
62
63 // Reconcile reads that state of the cluster for a GrafanaDataSource object and makes changes based on the state read
64 // and what is in the GrafanaDataSource.Spec
65 // Note:
66 // The Controller will requeue the Request to be processed again if the returned error is non-nil or
67 // Result.Requeue is true, otherwise upon completion it will remove the work from the queue.
68 func (r *ReconcileGrafanaDataSource) Reconcile(request reconcile.Request) (reconcile.Result, error) {
69         reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
70         reqLogger.Info("Reconciling GrafanaDataSource")
71
72         // Fetch the GrafanaDataSource instance
73         instance := &onapv1alpha1.GrafanaDataSource{}
74         err := r.client.Get(context.TODO(), request.NamespacedName, instance)
75         if err != nil {
76                 if errors.IsNotFound(err) {
77                         // Request object not found, could have been deleted after reconcile request.
78                         // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
79                         // Return and don't requeue
80                         return reconcile.Result{}, nil
81                 }
82                 // Error reading the object - requeue the request.
83
84                 return reconcile.Result{}, err
85         }
86
87         datasources := instance.Spec.Datasources
88         grafana := instance.Spec.Grafana
89
90         reqLogger.V(1).Info(" Datasource Name ", "datasources", datasources)
91
92         //loop through all datasources in the spec
93         for _, datasource := range datasources {
94
95                 //check if datasource exists
96                 grafanaURL := grafana["url"] + "/api/datasources/name/" + datasource.Name
97                 grafanaUsername := grafana["username"]
98                 grafanaPassword := grafana["password"]
99
100                 client := &http.Client{}
101                 req, err := http.NewRequest("GET", grafanaURL, nil)
102                 if err != nil {
103                         reqLogger.Error(err, "GET REQUEST error")
104                         return reconcile.Result{}, err
105                 }
106                 req.SetBasicAuth(grafanaUsername, grafanaPassword)
107                 getResp, err := client.Do(req)
108                 if err != nil {
109                         reqLogger.Error(err, "GET RESPONSE error")
110                         return reconcile.Result{}, err
111                 }
112
113                 defer getResp.Body.Close()
114
115                 //add datasource if datasource does not exist already
116                 if getResp.StatusCode == http.StatusNotFound {
117                         reqLogger.Info("Datasource does not exist, creating one...")
118                         // create datasource
119                         if err := createDataSource(grafana, datasource); err != nil {
120                                 return reconcile.Result{}, err
121                         }
122                 } else if getResp.StatusCode == http.StatusOK {
123                         //if datasource already exists
124                         reqLogger.V(1).Info("datasource already exists", "datasource", datasource.Name)
125                 } else {
126                         reqLogger.Error(err, "unknown error", datasource.Name)
127                 }
128
129         }
130         return reconcile.Result{}, nil
131 }
132
133 func createDataSource(grafana map[string]string, datasource onapv1alpha1.Datasource) error {
134         reqLogger := log.WithValues("Datasource name", datasource.Name, "Datasource URL", datasource.URL)
135         reqLogger.Info("creating datasource")
136
137         grafanaURL := grafana["url"] + "/api/datasources"
138         grafanaUsername := grafana["username"]
139         grafanaPassword := grafana["password"]
140
141         client := &http.Client{}
142         postBody, err := json.Marshal(datasource)
143         if err != nil {
144                 reqLogger.Error(err, "JSON Marshalling error")
145                 return err
146         }
147
148         req, err := http.NewRequest("POST", grafanaURL, bytes.NewBuffer(postBody))
149         if err != nil {
150                 reqLogger.Error(err, "POST REQUEST error")
151                 return err
152         }
153         req.Header.Set("Content-Type", "application/json")
154         req.SetBasicAuth(grafanaUsername, grafanaPassword)
155         postResp, err := client.Do(req)
156         if err != nil {
157                 reqLogger.Error(err, "POST RESPONSE error")
158                 return err
159         }
160         defer req.Body.Close()
161
162         if postResp.StatusCode == http.StatusOK {
163                 reqLogger.Info("Datasource created")
164                 return nil
165         }
166         return err
167 }