forked from kyma-project/btp-manager
-
Notifications
You must be signed in to change notification settings - Fork 0
/
serviceinstance_controller.go
143 lines (124 loc) · 4.24 KB
/
serviceinstance_controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package controllers
import (
"context"
"time"
"k8s.io/client-go/util/workqueue"
"sigs.k8s.io/controller-runtime/pkg/controller"
"github.com/kyma-project/btp-manager/internal/conditions"
"github.com/kyma-project/btp-manager/api/v1alpha1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
// ServiceInstanceReconciler reconciles a BtpOperator object in case of service instance changes
type ServiceInstanceReconciler struct {
client.Client
*rest.Config
Scheme *runtime.Scheme
}
func NewServiceInstanceReconciler(client client.Client, scheme *runtime.Scheme) *ServiceInstanceReconciler {
return &ServiceInstanceReconciler{
Client: client,
Scheme: scheme,
}
}
func (r *ServiceInstanceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx)
logger.Info("SI reconcile triggered")
list := &unstructured.UnstructuredList{}
list.SetGroupVersionKind(instanceGvk)
err := r.List(ctx, list, client.InNamespace(corev1.NamespaceAll))
if err != nil {
return ctrl.Result{}, err
}
if len(list.Items) != 0 {
return ctrl.Result{}, nil
}
list.SetGroupVersionKind(bindingGvk)
err = r.List(ctx, list, client.InNamespace(corev1.NamespaceAll))
if err != nil {
return ctrl.Result{}, err
}
if len(list.Items) != 0 {
return ctrl.Result{}, nil
}
btpOperator, err := r.getOldestBtpOperator(ctx)
if err != nil {
return ctrl.Result{}, err
}
// btp operator already removed
if btpOperator == nil {
return ctrl.Result{}, nil
}
if btpOperator.IsReasonStringEqual(string(conditions.ServiceInstancesAndBindingsNotCleaned)) {
return ctrl.Result{}, r.UpdateBtpOperatorStatus(ctx, btpOperator, v1alpha1.StateDeleting, conditions.HardDeleting, "BtpOperator is to be deleted")
}
return ctrl.Result{}, nil
}
func (r *ServiceInstanceReconciler) UpdateBtpOperatorStatus(ctx context.Context, cr *v1alpha1.BtpOperator, newState v1alpha1.State, reason conditions.Reason, message string) error {
cr.Status.WithState(newState)
newCondition := conditions.ConditionFromExistingReason(reason, message)
if newCondition != nil {
conditions.SetStatusCondition(&cr.Status.Conditions, *newCondition)
}
return r.Status().Update(ctx, cr)
}
// SetupWithManager sets up the controller with the Manager.
func (r *ServiceInstanceReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.Config = mgr.GetConfig()
si := &unstructured.Unstructured{}
si.SetGroupVersionKind(instanceGvk)
sb := &unstructured.Unstructured{}
sb.SetGroupVersionKind(bindingGvk)
return ctrl.NewControllerManagedBy(mgr).
For(si,
builder.WithPredicates(r.deletionPredicate())).
Watches(sb,
&handler.EnqueueRequestForObject{},
builder.WithPredicates(r.deletionPredicate())).
WithOptions(controller.Options{RateLimiter: workqueue.NewItemExponentialFailureRateLimiter(10*time.Millisecond, 1000*time.Second)}).
Complete(r)
}
func (r *ServiceInstanceReconciler) deletionPredicate() predicate.Predicate {
return predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
return false
},
DeleteFunc: func(e event.DeleteEvent) bool {
return true
},
UpdateFunc: func(e event.UpdateEvent) bool {
return false
},
GenericFunc: func(e event.GenericEvent) bool {
return false
},
}
}
func (r *ServiceInstanceReconciler) getOldestBtpOperator(ctx context.Context) (*v1alpha1.BtpOperator, error) {
logger := log.FromContext(ctx)
existingBtpOperators := &v1alpha1.BtpOperatorList{}
if err := r.List(ctx, existingBtpOperators); err != nil {
logger.Error(err, "unable to get existing BtpOperator CRs")
return nil, err
}
if len(existingBtpOperators.Items) == 0 {
return nil, nil
}
oldestCr := existingBtpOperators.Items[0]
for _, item := range existingBtpOperators.Items {
itemCreationTimestamp := &item.CreationTimestamp
if !(oldestCr.CreationTimestamp.Before(itemCreationTimestamp)) {
oldestCr = item
}
}
return &oldestCr, nil
}