71765e973fabe2978ea6349c37146cc4dfd9f6b2
[multicloud/k8s.git] / src / monitor / pkg / controller / resourcebundlestate / controller.go
1 package resourcebundlestate
2
3 import (
4         "context"
5         "log"
6
7         "github.com/onap/multicloud-k8s/src/monitor/pkg/apis/k8splugin/v1alpha1"
8
9         corev1 "k8s.io/api/core/v1"
10         k8serrors "k8s.io/apimachinery/pkg/api/errors"
11         "sigs.k8s.io/controller-runtime/pkg/client"
12         "sigs.k8s.io/controller-runtime/pkg/controller"
13         "sigs.k8s.io/controller-runtime/pkg/manager"
14         "sigs.k8s.io/controller-runtime/pkg/reconcile"
15         "sigs.k8s.io/controller-runtime/pkg/source"
16 )
17
18 // Add the new controller to the controller manager
19 func Add(mgr manager.Manager) error {
20         return add(mgr, newReconciler(mgr))
21 }
22
23 func add(mgr manager.Manager, r *reconciler) error {
24         // Create a new controller
25         c, err := controller.New("ResourceBundleState-controller", mgr, controller.Options{Reconciler: r})
26         if err != nil {
27                 return err
28         }
29
30         // Watch for changes to primary resource ResourceBundleState
31         err = c.Watch(&source.Kind{Type: &v1alpha1.ResourceBundleState{}}, &EventHandler{})
32         if err != nil {
33                 return err
34         }
35
36         return nil
37 }
38
39 func newReconciler(m manager.Manager) *reconciler {
40         return &reconciler{client: m.GetClient()}
41 }
42
43 type reconciler struct {
44         // Stores an array of all the ResourceBundleState
45         crList []v1alpha1.ResourceBundleState
46         client client.Client
47 }
48
49 // Reconcile implements the loop that will manage the ResourceBundleState CR
50 // We only accept CREATE events here and any subsequent changes are ignored.
51 func (r *reconciler) Reconcile(req reconcile.Request) (reconcile.Result, error) {
52         log.Printf("Reconciling ResourceBundleState %+v\n", req)
53
54         rbstate := &v1alpha1.ResourceBundleState{}
55         err := r.client.Get(context.TODO(), req.NamespacedName, rbstate)
56         if err != nil {
57                 if k8serrors.IsNotFound(err) {
58                         log.Printf("Object not found: %+v. Ignore as it must have been deleted.\n", req.NamespacedName)
59                         return reconcile.Result{}, nil
60                 }
61                 log.Printf("Failed to get object: %+v\n", req.NamespacedName)
62                 return reconcile.Result{}, err
63         }
64
65         err = r.updatePods(rbstate, rbstate.Spec.Selector.MatchLabels)
66         if err != nil {
67                 log.Printf("Error adding podstatuses: %v\n", err)
68                 return reconcile.Result{}, err
69         }
70
71         err = r.updateServices(rbstate, rbstate.Spec.Selector.MatchLabels)
72         if err != nil {
73                 log.Printf("Error adding services: %v\n", err)
74                 return reconcile.Result{}, err
75         }
76
77         // TODO: Update this based on the statuses of the lower resources
78         rbstate.Status.Ready = false
79         err = r.client.Status().Update(context.TODO(), rbstate)
80         if err != nil {
81                 log.Printf("failed to update rbstate: %v\n", err)
82                 return reconcile.Result{}, err
83         }
84
85         return reconcile.Result{}, nil
86 }
87
88 func (r *reconciler) updateServices(rbstate *v1alpha1.ResourceBundleState,
89         selectors map[string]string) error {
90
91         // Update the CR with the Services created as well
92         serviceList := &corev1.ServiceList{}
93         err := listResources(r.client, rbstate.Namespace, selectors, serviceList)
94         if err != nil {
95                 log.Printf("Failed to list services: %v", err)
96                 return err
97         }
98
99         rbstate.Status.ServiceStatuses = serviceList.Items
100         return nil
101 }
102
103 func (r *reconciler) updatePods(rbstate *v1alpha1.ResourceBundleState,
104         selectors map[string]string) error {
105
106         // Update the CR with the pods tracked
107         podList := &corev1.PodList{}
108         err := listResources(r.client, rbstate.Namespace, selectors, podList)
109         if err != nil {
110                 log.Printf("Failed to list pods: %v", err)
111                 return err
112         }
113
114         rbstate.Status.PodStatuses = []v1alpha1.PodStatus{}
115
116         for _, pod := range podList.Items {
117                 resStatus := v1alpha1.PodStatus{
118                         ObjectMeta: pod.ObjectMeta,
119                         Ready:      false,
120                         Status:     pod.Status,
121                 }
122                 rbstate.Status.PodStatuses = append(rbstate.Status.PodStatuses, resStatus)
123         }
124
125         return nil
126 }