@@ -18,46 +18,176 @@ package storageclusterpeer
18
18
19
19
import (
20
20
"context"
21
+ "fmt"
22
+ "time"
21
23
24
+ ocsv1 "github.com/red-hat-storage/ocs-operator/api/v4/v1"
25
+ providerClient "github.com/red-hat-storage/ocs-operator/services/provider/api/v4/client"
26
+
27
+ "github.com/go-logr/logr"
28
+ "google.golang.org/grpc/status"
29
+ "k8s.io/apimachinery/pkg/api/errors"
22
30
"k8s.io/apimachinery/pkg/runtime"
23
31
ctrl "sigs.k8s.io/controller-runtime"
24
32
"sigs.k8s.io/controller-runtime/pkg/client"
33
+ "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
25
34
"sigs.k8s.io/controller-runtime/pkg/log"
35
+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
36
+ )
26
37
27
- v1 "github.com/red-hat-storage/ocs-operator/api/v4/v1"
38
+ const (
39
+ storageClusterPeerFinalizer = "storageclusterpeer.ocs.openshift.io"
28
40
)
29
41
30
42
// StorageClusterPeerReconciler reconciles a StorageClusterPeer object
31
43
// nolint:revive
32
44
type StorageClusterPeerReconciler struct {
33
45
client.Client
34
46
Scheme * runtime.Scheme
47
+
48
+ log logr.Logger
49
+ ctx context.Context
50
+ storageClusterPeer * ocsv1.StorageClusterPeer
51
+ storageCluster * ocsv1.StorageCluster
52
+ }
53
+
54
+ // SetupWithManager sets up the controller with the Manager.
55
+ func (r * StorageClusterPeerReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
56
+ return ctrl .NewControllerManagedBy (mgr ).
57
+ For (& ocsv1.StorageClusterPeer {}).
58
+ Complete (r )
35
59
}
36
60
37
61
//+kubebuilder:rbac:groups=ocs.openshift.io,resources=storageclusterpeers,verbs=get;list;watch;create;update;patch;delete
38
62
//+kubebuilder:rbac:groups=ocs.openshift.io,resources=storageclusterpeers/status,verbs=get;update;patch
39
63
//+kubebuilder:rbac:groups=ocs.openshift.io,resources=storageclusterpeers/finalizers,verbs=update
64
+ //+kubebuilder:rbac:groups=ocs.openshift.io,resources=storageclusters,verbs=get;list;watch
40
65
41
66
// Reconcile is part of the main kubernetes reconciliation loop which aims to
42
67
// move the current state of the cluster closer to the desired state.
43
- // TODO(user): Modify the Reconcile function to compare the state specified by
44
- // the StorageClusterPeer object against the actual cluster state, and then
45
- // perform operations to make the cluster state reflect the state specified by
46
- // the user.
47
- //
48
- // For more details, check Reconcile and its Result here:
49
- // - https://pkg.go.dev/sigs.k8s.io/[email protected] /pkg/reconcile
50
- func (r * StorageClusterPeerReconciler ) Reconcile (ctx context.Context , _ ctrl.Request ) (ctrl.Result , error ) {
51
- _ = log .FromContext (ctx )
52
-
53
- // TODO(user): your logic here
68
+ func (r * StorageClusterPeerReconciler ) Reconcile (ctx context.Context , request ctrl.Request ) (ctrl.Result , error ) {
69
+ var err error
70
+ r .ctx = ctx
71
+ r .log = log .FromContext (ctx , "StorageClient" , request )
72
+ r .log .Info ("Reconciling StorageClusterPeer." )
73
+
74
+ // Fetch StorageCluster(s)
75
+ storageClusterList := & ocsv1.StorageClusterList {}
76
+ err = r .list (storageClusterList , client .InNamespace (request .Namespace ))
77
+ if err != nil {
78
+ r .log .Error (err , "StorageCluster for StorageClusterPeer found in the same namespace." )
79
+ return ctrl.Result {}, err
80
+ }
81
+
82
+ if len (storageClusterList .Items ) != 1 {
83
+ err := fmt .Errorf ("invalid number of StorageCluster found" )
84
+ r .log .Error (err , "invalid number of StorageCluster(s) found, expected 1, found %v" , len (storageClusterList .Items ))
85
+ return ctrl.Result {}, err
86
+ }
87
+
88
+ r .storageCluster = & storageClusterList .Items [0 ]
89
+
90
+ // Fetch the StorageClusterPeer instance
91
+ r .storageClusterPeer = & ocsv1.StorageClusterPeer {}
92
+ r .storageClusterPeer .Name = request .Name
93
+ r .storageClusterPeer .Namespace = request .Namespace
94
+
95
+ if err = r .get (r .storageClusterPeer ); err != nil {
96
+ if errors .IsNotFound (err ) {
97
+ r .log .Info ("StorageClusterPeer resource not found. Ignoring since object must be deleted." )
98
+ return reconcile.Result {}, nil
99
+ }
100
+ r .log .Error (err , "Failed to get StorageClusterPeer." )
101
+ return reconcile.Result {}, err
102
+ }
103
+
104
+ result , reconcileErr := r .reconcilePhases ()
105
+
106
+ // Apply status changes to the StorageClient
107
+ statusErr := r .Client .Status ().Update (ctx , r .storageClusterPeer )
108
+ if statusErr != nil {
109
+ r .log .Error (statusErr , "Failed to update StorageClusterPeer status." )
110
+ }
111
+
112
+ if reconcileErr != nil {
113
+ err = reconcileErr
114
+ } else if statusErr != nil {
115
+ err = statusErr
116
+ }
117
+
118
+ return result , err
119
+ }
120
+
121
+ func (r * StorageClusterPeerReconciler ) reconcilePhases () (ctrl.Result , error ) {
122
+ ocsClient , err := r .newExternalClusterClient ()
123
+ if err != nil {
124
+ return reconcile.Result {}, err
125
+ }
126
+ defer ocsClient .Close ()
127
+
128
+ // marked for deletion
129
+ if ! r .storageClusterPeer .GetDeletionTimestamp ().IsZero () {
130
+ //TODO: Removing PeerOCS Call
131
+
132
+ if controllerutil .RemoveFinalizer (r .storageClusterPeer , storageClusterPeerFinalizer ) {
133
+ r .log .Info ("removing finalizer from StorageClusterPeer." , "StorageClusterPeer" , r .storageClusterPeer .Name )
134
+ if err := r .update (r .storageClusterPeer ); err != nil {
135
+ r .log .Info ("Failed to remove finalizer from StorageClusterPeer" , "StorageClusterPeer" , r .storageClusterPeer .Name )
136
+ return reconcile.Result {}, fmt .Errorf ("failed to remove finalizer from StorageClient: %v" , err )
137
+ }
138
+ }
139
+ }
140
+
141
+ if controllerutil .AddFinalizer (r .storageClusterPeer , storageClusterPeerFinalizer ) {
142
+ r .log .Info ("Finalizer not found for StorageClusterPeer. Adding finalizer." , "StorageClusterPeer" , r .storageClusterPeer .Name )
143
+ if err := r .update (r .storageClusterPeer ); err != nil {
144
+ return reconcile.Result {}, fmt .Errorf ("failed to update StorageClusterPeer: %v" , err )
145
+ }
146
+ }
147
+
148
+ if r .storageClusterPeer .Status .State != ocsv1 .StorageClusterPeerRemoteStatePeered {
149
+ return r .peerOCS (ocsClient )
150
+ }
54
151
55
152
return ctrl.Result {}, nil
56
153
}
57
154
58
- // SetupWithManager sets up the controller with the Manager.
59
- func (r * StorageClusterPeerReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
60
- return ctrl .NewControllerManagedBy (mgr ).
61
- For (& v1.StorageClusterPeer {}).
62
- Complete (r )
155
+ func (r * StorageClusterPeerReconciler ) newExternalClusterClient () (* providerClient.OCSProviderClient , error ) {
156
+
157
+ ocsProviderClient , err := providerClient .NewProviderClient (
158
+ r .ctx , r .storageClusterPeer .Spec .ApiEndpoint , time .Second * 10 )
159
+ if err != nil {
160
+ return nil , fmt .Errorf ("failed to create a new provider client: %v" , err )
161
+ }
162
+
163
+ return ocsProviderClient , nil
164
+ }
165
+
166
+ func (r * StorageClusterPeerReconciler ) peerOCS (ocsClient * providerClient.OCSProviderClient ) (ctrl.Result , error ) {
167
+ r .storageClusterPeer .Status .State = ocsv1 .StorageClusterPeerRemoteStatePeering
168
+ response , err := ocsClient .PeerStorageCluster (r .ctx , r .storageClusterPeer .Spec .OnboardingToken , string (r .storageCluster .UID ))
169
+ if err != nil {
170
+ r .log .Error (err , fmt .Sprintf ("failed to Peer Storage Cluster, code: %v." , status .Code (err )))
171
+ return ctrl.Result {}, err
172
+ }
173
+ if r .storageClusterPeer .Status .RemoteStorageClusterUID != response .StorageClusterUID {
174
+ err := fmt .Errorf ("falied to validate remote Storage Cluster UID against PeerOCS Response" )
175
+ r .log .Error (err , "failed to Peer Storage Cluster" )
176
+ return ctrl.Result {}, err
177
+ }
178
+ r .storageClusterPeer .Status .State = ocsv1 .StorageClusterPeerRemoteStatePeered
179
+ return ctrl.Result {}, nil
180
+ }
181
+
182
+ func (r * StorageClusterPeerReconciler ) get (obj client.Object ) error {
183
+ key := client .ObjectKeyFromObject (obj )
184
+ return r .Client .Get (r .ctx , key , obj )
185
+ }
186
+
187
+ func (r * StorageClusterPeerReconciler ) list (obj client.ObjectList , listOptions ... client.ListOption ) error {
188
+ return r .Client .List (r .ctx , obj , listOptions ... )
189
+ }
190
+
191
+ func (r * StorageClusterPeerReconciler ) update (obj client.Object , opts ... client.UpdateOption ) error {
192
+ return r .Client .Update (r .ctx , obj , opts ... )
63
193
}
0 commit comments