1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package remotechaosmonitor
17
18 import (
19 "context"
20 "reflect"
21
22 "github.com/go-logr/logr"
23 apierrors "k8s.io/apimachinery/pkg/api/errors"
24 "k8s.io/client-go/util/retry"
25 ctrl "sigs.k8s.io/controller-runtime"
26 "sigs.k8s.io/controller-runtime/pkg/client"
27
28 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
29 )
30
31 type Reconciler struct {
32 clusterName string
33
34 obj v1alpha1.InnerObject
35
36 logger logr.Logger
37 localClient client.Client
38 remoteClient client.Client
39 }
40
41 func New(obj v1alpha1.InnerObject, manageClient client.Client, clusterName string, localClient client.Client, logger logr.Logger) *Reconciler {
42 return &Reconciler{
43 clusterName: clusterName,
44 obj: obj,
45 logger: logger.WithName("remotechaos-monitor"),
46 localClient: manageClient,
47 remoteClient: localClient,
48 }
49 }
50
51 func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
52 r.logger.Info("reconcile chaos", "clusterName", r.clusterName, "namespace", req.Namespace, "name", req.Name)
53
54 shouldDelete := false
55 remoteObj := r.obj.DeepCopyObject().(v1alpha1.RemoteObject)
56 err := r.remoteClient.Get(ctx, req.NamespacedName, remoteObj)
57 if err != nil {
58 if apierrors.IsNotFound(err) {
59 r.logger.Info("chaos not found")
60
61 shouldDelete = true
62 } else {
63
64 r.logger.Error(err, "unable to get remote chaos")
65 return ctrl.Result{}, nil
66 }
67 }
68
69 localObj := r.obj.DeepCopyObject().(v1alpha1.RemoteObject)
70 err = r.localClient.Get(ctx, req.NamespacedName, localObj)
71 if err != nil {
72 if apierrors.IsNotFound(err) {
73 r.logger.Info("local chaos not found")
74
75 err = r.remoteClient.Delete(ctx, remoteObj)
76 if err != nil {
77 if apierrors.IsNotFound(err) {
78 r.logger.Info("remote chaos deleted")
79 } else {
80
81 r.logger.Error(err, "unable to get remote chaos")
82 }
83 }
84
85 return ctrl.Result{}, nil
86 }
87
88
89 r.logger.Error(err, "unable to get local chaos")
90 return ctrl.Result{}, nil
91 }
92
93 if shouldDelete {
94 r.logger.Info("deleting local obj", "namespace", localObj.GetNamespace(), "name", localObj.GetName())
95 localObj.SetFinalizers([]string{})
96 err := r.localClient.Update(ctx, localObj)
97 if err != nil {
98
99 r.logger.Error(err, "fail to update localObj")
100
101
102 }
103
104 err = r.localClient.Delete(ctx, localObj)
105 if err != nil {
106
107 r.logger.Error(err, "fail to delete local object")
108 }
109
110 return ctrl.Result{}, nil
111 }
112
113 shouldUpdate := false
114 if !reflect.DeepEqual(localObj.GetFinalizers(), remoteObj.GetFinalizers()) {
115 r.logger.Info("setting new finalizers")
116 localObj.SetFinalizers(remoteObj.GetFinalizers())
117
118 shouldUpdate = true
119 }
120
121
122 if !reflect.DeepEqual(localObj.GetStatus(), remoteObj.GetStatus()) {
123 r.logger.Info("setting new status", "local:", localObj.GetStatus(), "remote:", remoteObj.GetStatus())
124 shouldUpdate = true
125 }
126
127 if shouldUpdate {
128 retry.RetryOnConflict(retry.DefaultRetry, func() error {
129 localObj := r.obj.DeepCopyObject().(v1alpha1.RemoteObject)
130 err = r.localClient.Get(ctx, req.NamespacedName, localObj)
131 if err != nil {
132 return err
133 }
134
135
136 localObj.SetFinalizers(remoteObj.GetFinalizers())
137 remoteObj.GetStatus().DeepCopyInto(localObj.GetStatus())
138 return r.localClient.Update(ctx, localObj)
139 })
140 }
141 return ctrl.Result{}, nil
142 }
143