...
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package finalizers
15
16 import (
17 "context"
18
19 "github.com/go-logr/logr"
20 apierrors "k8s.io/apimachinery/pkg/api/errors"
21 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22 "k8s.io/client-go/util/retry"
23 ctrl "sigs.k8s.io/controller-runtime"
24 "sigs.k8s.io/controller-runtime/pkg/client"
25
26 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
27 "github.com/chaos-mesh/chaos-mesh/controllers/utils/recorder"
28 )
29
30 const (
31
32 AnnotationCleanFinalizer = `chaos-mesh.chaos-mesh.org/cleanFinalizer`
33
34 AnnotationCleanFinalizerForced = `forced`
35
36 RecordFinalizer = "chaos-mesh/records"
37 )
38
39
40 type Reconciler struct {
41
42 Object v1alpha1.InnerObject
43
44
45 client.Client
46
47 Recorder recorder.ChaosRecorder
48
49 Log logr.Logger
50 }
51
52
53 func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
54 obj := r.Object.DeepCopyObject().(v1alpha1.InnerObject)
55
56 if err := r.Client.Get(context.TODO(), req.NamespacedName, obj); err != nil {
57 if apierrors.IsNotFound(err) {
58 r.Log.Info("chaos not found")
59 } else {
60
61 r.Log.Error(err, "unable to get chaos")
62 }
63 return ctrl.Result{}, nil
64 }
65
66 finalizers := obj.GetObjectMeta().Finalizers
67 records := obj.GetStatus().Experiment.Records
68 shouldUpdate := false
69 if obj.IsDeleted() {
70 resumed := true
71 for _, record := range records {
72 if record.Phase != v1alpha1.NotInjected {
73 resumed = false
74 }
75 }
76
77 if obj.GetObjectMeta().Annotations[AnnotationCleanFinalizer] == AnnotationCleanFinalizerForced || (resumed && len(finalizers) != 0) {
78 r.Recorder.Event(obj, recorder.FinalizerRemoved{})
79 finalizers = []string{}
80 shouldUpdate = true
81 }
82 } else {
83 if !ContainsFinalizer(obj.(metav1.Object), RecordFinalizer) {
84 r.Recorder.Event(obj, recorder.FinalizerInited{})
85 shouldUpdate = true
86 finalizers = append(obj.GetObjectMeta().Finalizers, RecordFinalizer)
87 }
88 }
89
90 if shouldUpdate {
91 updateError := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
92 obj := r.Object.DeepCopyObject().(v1alpha1.InnerObject)
93
94 if err := r.Client.Get(context.TODO(), req.NamespacedName, obj); err != nil {
95 r.Log.Error(err, "unable to get chaos")
96 return err
97 }
98
99 obj.GetObjectMeta().Finalizers = finalizers
100 return r.Client.Update(context.TODO(), obj)
101 })
102 if updateError != nil {
103
104 r.Log.Error(updateError, "fail to update")
105 r.Recorder.Event(obj, recorder.Failed{
106 Activity: "update finalizer",
107 Err: "updateError.Error()",
108 })
109 return ctrl.Result{}, nil
110 }
111
112 r.Recorder.Event(obj, recorder.Updated{
113 Field: "finalizer",
114 })
115 }
116 return ctrl.Result{}, nil
117 }
118
119
120 func ContainsFinalizer(o metav1.Object, finalizer string) bool {
121 f := o.GetFinalizers()
122 for _, e := range f {
123 if e == finalizer {
124 return true
125 }
126 }
127 return false
128 }
129