7206116bdcca3163f8e9652d2636167fbd51c359
[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         appsv1 "k8s.io/api/apps/v1"
10         v1 "k8s.io/api/batch/v1"
11         corev1 "k8s.io/api/core/v1"
12         v1beta1 "k8s.io/api/extensions/v1beta1"
13         k8serrors "k8s.io/apimachinery/pkg/api/errors"
14         "sigs.k8s.io/controller-runtime/pkg/client"
15         "sigs.k8s.io/controller-runtime/pkg/controller"
16         "sigs.k8s.io/controller-runtime/pkg/manager"
17         "sigs.k8s.io/controller-runtime/pkg/reconcile"
18         "sigs.k8s.io/controller-runtime/pkg/source"
19 )
20
21 // Add the new controller to the controller manager
22 func Add(mgr manager.Manager) error {
23         return add(mgr, newReconciler(mgr))
24 }
25
26 func add(mgr manager.Manager, r *reconciler) error {
27         // Create a new controller
28         c, err := controller.New("ResourceBundleState-controller", mgr, controller.Options{Reconciler: r})
29         if err != nil {
30                 return err
31         }
32
33         // Watch for changes to primary resource ResourceBundleState
34         err = c.Watch(&source.Kind{Type: &v1alpha1.ResourceBundleState{}}, &EventHandler{})
35         if err != nil {
36                 return err
37         }
38
39         return nil
40 }
41
42 func newReconciler(m manager.Manager) *reconciler {
43         return &reconciler{client: m.GetClient()}
44 }
45
46 type reconciler struct {
47         // Stores an array of all the ResourceBundleState
48         crList []v1alpha1.ResourceBundleState
49         client client.Client
50 }
51
52 // Reconcile implements the loop that will manage the ResourceBundleState CR
53 // We only accept CREATE events here and any subsequent changes are ignored.
54 func (r *reconciler) Reconcile(req reconcile.Request) (reconcile.Result, error) {
55         log.Printf("Reconciling ResourceBundleState %+v\n", req)
56
57         rbstate := &v1alpha1.ResourceBundleState{}
58         err := r.client.Get(context.TODO(), req.NamespacedName, rbstate)
59         if err != nil {
60                 if k8serrors.IsNotFound(err) {
61                         log.Printf("Object not found: %+v. Ignore as it must have been deleted.\n", req.NamespacedName)
62                         return reconcile.Result{}, nil
63                 }
64                 log.Printf("Failed to get object: %+v\n", req.NamespacedName)
65                 return reconcile.Result{}, err
66         }
67
68         err = r.updatePods(rbstate, rbstate.Spec.Selector.MatchLabels)
69         if err != nil {
70                 log.Printf("Error adding podstatuses: %v\n", err)
71                 return reconcile.Result{}, err
72         }
73
74         err = r.updateServices(rbstate, rbstate.Spec.Selector.MatchLabels)
75         if err != nil {
76                 log.Printf("Error adding servicestatuses: %v\n", err)
77                 return reconcile.Result{}, err
78         }
79
80         err = r.updateConfigMaps(rbstate, rbstate.Spec.Selector.MatchLabels)
81         if err != nil {
82                 log.Printf("Error adding configmapstatuses: %v\n", err)
83                 return reconcile.Result{}, err
84         }
85
86         err = r.updateDeployments(rbstate, rbstate.Spec.Selector.MatchLabels)
87         if err != nil {
88                 log.Printf("Error adding deploymentstatuses: %v\n", err)
89                 return reconcile.Result{}, err
90         }
91
92         err = r.updateSecrets(rbstate, rbstate.Spec.Selector.MatchLabels)
93         if err != nil {
94                 log.Printf("Error adding secretstatuses: %v\n", err)
95                 return reconcile.Result{}, err
96         }
97
98         err = r.updateDaemonSets(rbstate, rbstate.Spec.Selector.MatchLabels)
99         if err != nil {
100                 log.Printf("Error adding daemonSetstatuses: %v\n", err)
101                 return reconcile.Result{}, err
102         }
103
104         err = r.updateIngresses(rbstate, rbstate.Spec.Selector.MatchLabels)
105         if err != nil {
106                 log.Printf("Error adding ingressStatuses: %v\n", err)
107                 return reconcile.Result{}, err
108         }
109
110         err = r.updateJobs(rbstate, rbstate.Spec.Selector.MatchLabels)
111         if err != nil {
112                 log.Printf("Error adding jobstatuses: %v\n", err)
113                 return reconcile.Result{}, err
114         }
115
116         err = r.updateStatefulSets(rbstate, rbstate.Spec.Selector.MatchLabels)
117         if err != nil {
118                 log.Printf("Error adding statefulSetstatuses: %v\n", err)
119                 return reconcile.Result{}, err
120         }
121
122         // TODO: Update this based on the statuses of the lower resources
123         rbstate.Status.Ready = false
124         err = r.client.Status().Update(context.TODO(), rbstate)
125         if err != nil {
126                 log.Printf("failed to update rbstate: %v\n", err)
127                 return reconcile.Result{}, err
128         }
129
130         return reconcile.Result{}, nil
131 }
132
133 func (r *reconciler) updateServices(rbstate *v1alpha1.ResourceBundleState,
134         selectors map[string]string) error {
135
136         // Update the CR with the Services created as well
137         serviceList := &corev1.ServiceList{}
138         err := listResources(r.client, rbstate.Namespace, selectors, serviceList)
139         if err != nil {
140                 log.Printf("Failed to list services: %v", err)
141                 return err
142         }
143
144         rbstate.Status.ServiceStatuses = []corev1.Service{}
145
146         for _, svc := range serviceList.Items {
147                 resStatus := corev1.Service{
148                         ObjectMeta: svc.ObjectMeta,
149                         Status:     svc.Status,
150                 }
151                 rbstate.Status.ServiceStatuses = append(rbstate.Status.ServiceStatuses, resStatus)
152         }
153
154         return nil
155 }
156
157 func (r *reconciler) updatePods(rbstate *v1alpha1.ResourceBundleState,
158         selectors map[string]string) error {
159
160         // Update the CR with the pods tracked
161         podList := &corev1.PodList{}
162         err := listResources(r.client, rbstate.Namespace, selectors, podList)
163         if err != nil {
164                 log.Printf("Failed to list pods: %v", err)
165                 return err
166         }
167
168         rbstate.Status.PodStatuses = []v1alpha1.PodStatus{}
169
170         for _, pod := range podList.Items {
171                 resStatus := v1alpha1.PodStatus{
172                         ObjectMeta: pod.ObjectMeta,
173                         Ready:      false,
174                         Status:     pod.Status,
175                 }
176                 rbstate.Status.PodStatuses = append(rbstate.Status.PodStatuses, resStatus)
177         }
178
179         return nil
180 }
181
182 func (r *reconciler) updateConfigMaps(rbstate *v1alpha1.ResourceBundleState,
183         selectors map[string]string) error {
184
185         // Update the CR with the ConfigMaps created as well
186         configMapList := &corev1.ConfigMapList{}
187         err := listResources(r.client, rbstate.Namespace, selectors, configMapList)
188         if err != nil {
189                 log.Printf("Failed to list configMaps: %v", err)
190                 return err
191         }
192
193         rbstate.Status.ConfigMapStatuses = []corev1.ConfigMap{}
194
195         for _, cm := range configMapList.Items {
196                 resStatus := corev1.ConfigMap{
197                         ObjectMeta: cm.ObjectMeta,
198                 }
199                 rbstate.Status.ConfigMapStatuses = append(rbstate.Status.ConfigMapStatuses, resStatus)
200         }
201
202         return nil
203 }
204
205 func (r *reconciler) updateDeployments(rbstate *v1alpha1.ResourceBundleState,
206         selectors map[string]string) error {
207
208         // Update the CR with the Deployments created as well
209         deploymentList := &appsv1.DeploymentList{}
210         err := listResources(r.client, rbstate.Namespace, selectors, deploymentList)
211         if err != nil {
212                 log.Printf("Failed to list deployments: %v", err)
213                 return err
214         }
215
216         rbstate.Status.DeploymentStatuses = []appsv1.Deployment{}
217
218         for _, dep := range deploymentList.Items {
219                 resStatus := appsv1.Deployment{
220                         ObjectMeta: dep.ObjectMeta,
221                         Status:     dep.Status,
222                 }
223                 rbstate.Status.DeploymentStatuses = append(rbstate.Status.DeploymentStatuses, resStatus)
224         }
225
226         return nil
227 }
228
229 func (r *reconciler) updateSecrets(rbstate *v1alpha1.ResourceBundleState,
230         selectors map[string]string) error {
231
232         // Update the CR with the Secrets created as well
233         secretList := &corev1.SecretList{}
234         err := listResources(r.client, rbstate.Namespace, selectors, secretList)
235         if err != nil {
236                 log.Printf("Failed to list secrets: %v", err)
237                 return err
238         }
239
240         rbstate.Status.SecretStatuses = []corev1.Secret{}
241
242         for _, sec := range secretList.Items {
243                 resStatus := corev1.Secret{
244                         ObjectMeta: sec.ObjectMeta,
245                 }
246                 rbstate.Status.SecretStatuses = append(rbstate.Status.SecretStatuses, resStatus)
247         }
248
249         return nil
250 }
251
252 func (r *reconciler) updateDaemonSets(rbstate *v1alpha1.ResourceBundleState,
253         selectors map[string]string) error {
254
255         // Update the CR with the DaemonSets created as well
256         daemonSetList := &appsv1.DaemonSetList{}
257         err := listResources(r.client, rbstate.Namespace, selectors, daemonSetList)
258         if err != nil {
259                 log.Printf("Failed to list DaemonSets: %v", err)
260                 return err
261         }
262
263         rbstate.Status.DaemonSetStatuses = []appsv1.DaemonSet{}
264
265         for _, ds := range daemonSetList.Items {
266                 resStatus := appsv1.DaemonSet{
267                         ObjectMeta: ds.ObjectMeta,
268                         Status:     ds.Status,
269                 }
270                 rbstate.Status.DaemonSetStatuses = append(rbstate.Status.DaemonSetStatuses, resStatus)
271         }
272
273         return nil
274 }
275
276 func (r *reconciler) updateIngresses(rbstate *v1alpha1.ResourceBundleState,
277         selectors map[string]string) error {
278
279         // Update the CR with the Ingresses created as well
280         ingressList := &v1beta1.IngressList{}
281         err := listResources(r.client, rbstate.Namespace, selectors, ingressList)
282         if err != nil {
283                 log.Printf("Failed to list ingresses: %v", err)
284                 return err
285         }
286
287         rbstate.Status.IngressStatuses = []v1beta1.Ingress{}
288
289         for _, ing := range ingressList.Items {
290                 resStatus := v1beta1.Ingress{
291                         ObjectMeta: ing.ObjectMeta,
292                         Status:     ing.Status,
293                 }
294                 rbstate.Status.IngressStatuses = append(rbstate.Status.IngressStatuses, resStatus)
295         }
296
297         return nil
298 }
299
300 func (r *reconciler) updateJobs(rbstate *v1alpha1.ResourceBundleState,
301         selectors map[string]string) error {
302
303         // Update the CR with the Services created as well
304         jobList := &v1.JobList{}
305         err := listResources(r.client, rbstate.Namespace, selectors, jobList)
306         if err != nil {
307                 log.Printf("Failed to list jobs: %v", err)
308                 return err
309         }
310
311         rbstate.Status.JobStatuses = []v1.Job{}
312
313         for _, job := range jobList.Items {
314                 resStatus := v1.Job{
315                         ObjectMeta: job.ObjectMeta,
316                         Status:     job.Status,
317                 }
318                 rbstate.Status.JobStatuses = append(rbstate.Status.JobStatuses, resStatus)
319         }
320
321         return nil
322 }
323
324 func (r *reconciler) updateStatefulSets(rbstate *v1alpha1.ResourceBundleState,
325         selectors map[string]string) error {
326
327         // Update the CR with the StatefulSets created as well
328         statefulSetList := &appsv1.StatefulSetList{}
329         err := listResources(r.client, rbstate.Namespace, selectors, statefulSetList)
330         if err != nil {
331                 log.Printf("Failed to list statefulSets: %v", err)
332                 return err
333         }
334
335         rbstate.Status.StatefulSetStatuses = []appsv1.StatefulSet{}
336
337         for _, sfs := range statefulSetList.Items {
338                 resStatus := appsv1.StatefulSet{
339                         ObjectMeta: sfs.ObjectMeta,
340                         Status:     sfs.Status,
341                 }
342                 rbstate.Status.StatefulSetStatuses = append(rbstate.Status.StatefulSetStatuses, resStatus)
343         }
344
345         return nil
346 }