@@ -45,11 +45,11 @@ type OperatorReconciler struct {
45
45
client.Client
46
46
47
47
log logr.Logger
48
- mu sync.RWMutex
49
48
factory decorators.OperatorFactory
50
49
51
- // operators contains the names of Operators the OperatorReconciler has observed exist.
52
- operators map [types.NamespacedName ]struct {}
50
+ // last observed resourceVersion for known Operators
51
+ lastResourceVersion map [types.NamespacedName ]string
52
+ mu sync.RWMutex
53
53
}
54
54
55
55
// +kubebuilder:rbac:groups=operators.coreos.com,resources=operators,verbs=create;update;patch;delete
@@ -101,9 +101,9 @@ func NewOperatorReconciler(cli client.Client, log logr.Logger, scheme *runtime.S
101
101
return & OperatorReconciler {
102
102
Client : cli ,
103
103
104
- log : log ,
105
- factory : factory ,
106
- operators : map [types.NamespacedName ]struct {} {},
104
+ log : log ,
105
+ factory : factory ,
106
+ lastResourceVersion : map [types.NamespacedName ]string {},
107
107
}, nil
108
108
}
109
109
@@ -115,40 +115,55 @@ func (r *OperatorReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
115
115
log := r .log .WithValues ("request" , req )
116
116
log .V (1 ).Info ("reconciling operator" )
117
117
118
- // Fetch the Operator from the cache
118
+ // Get the Operator
119
119
ctx := context .TODO ()
120
+ create := false
121
+ name := req .NamespacedName .Name
120
122
in := & operatorsv1.Operator {}
121
123
if err := r .Get (ctx , req .NamespacedName , in ); err != nil {
122
124
if apierrors .IsNotFound (err ) {
123
- log .Info ("Could not find Operator" )
124
- r .unobserve (req .NamespacedName )
125
- // TODO(njhale): Recreate operator if we can find any components.
125
+ create = true
126
+ in .SetName (name )
126
127
} else {
127
- log .Error (err , "Error finding Operator" )
128
+ log .Error (err , "Error requesting Operator" )
129
+ return reconcile.Result {Requeue : true }, nil
128
130
}
131
+ }
129
132
130
- return reconcile.Result {}, nil
133
+ if ! create {
134
+ if rv , ok := r .getLastResourceVersion (req .NamespacedName ); ok && rv == in .ResourceVersion {
135
+ log .V (1 ).Info ("Operator is already up-to-date" )
136
+ return reconcile.Result {}, nil
137
+ }
131
138
}
132
- r .observe (req .NamespacedName )
133
139
134
140
// Wrap with convenience decorator
135
141
operator , err := r .factory .NewOperator (in )
136
142
if err != nil {
137
143
log .Error (err , "Could not wrap Operator with convenience decorator" )
138
- return reconcile.Result {}, nil
144
+ return reconcile.Result {Requeue : true }, nil
139
145
}
140
146
141
147
if err = r .updateComponents (ctx , operator ); err != nil {
142
148
log .Error (err , "Could not update components" )
143
- return reconcile.Result {}, nil
149
+ return reconcile.Result {Requeue : true }, nil
144
150
145
151
}
146
152
147
- if err := r .Status ().Update (ctx , operator .Operator ); err != nil {
148
- log .Error (err , "Could not update Operator status" )
149
- return ctrl.Result {}, err
153
+ if create {
154
+ if err := r .Create (context .Background (), operator .Operator ); err != nil && ! apierrors .IsAlreadyExists (err ) {
155
+ r .log .Error (err , "Could not create Operator" , "operator" , name )
156
+ return ctrl.Result {Requeue : true }, nil
157
+ }
158
+ } else {
159
+ if err := r .Status ().Update (ctx , operator .Operator ); err != nil {
160
+ log .Error (err , "Could not update Operator status" )
161
+ return ctrl.Result {Requeue : true }, nil
162
+ }
150
163
}
151
164
165
+ r .setLastResourceVersion (req .NamespacedName , operator .GetResourceVersion ())
166
+
152
167
return ctrl.Result {}, nil
153
168
}
154
169
@@ -196,45 +211,36 @@ func (r *OperatorReconciler) listComponents(ctx context.Context, selector labels
196
211
return componentLists , nil
197
212
}
198
213
199
- func (r * OperatorReconciler ) observed (name types.NamespacedName ) bool {
214
+ func (r * OperatorReconciler ) getLastResourceVersion (name types.NamespacedName ) ( string , bool ) {
200
215
r .mu .RLock ()
201
216
defer r .mu .RUnlock ()
202
- _ , ok := r .operators [name ]
203
- return ok
217
+ rv , ok := r .lastResourceVersion [name ]
218
+ return rv , ok
204
219
}
205
220
206
- func (r * OperatorReconciler ) observe (name types.NamespacedName ) {
221
+ func (r * OperatorReconciler ) setLastResourceVersion (name types.NamespacedName , rv string ) {
207
222
r .mu .Lock ()
208
223
defer r .mu .Unlock ()
209
- r .operators [name ] = struct {}{}
224
+ r .lastResourceVersion [name ] = rv
210
225
}
211
226
212
- func (r * OperatorReconciler ) unobserve (name types.NamespacedName ) {
227
+ func (r * OperatorReconciler ) unsetLastResourceVersion (name types.NamespacedName ) {
213
228
r .mu .Lock ()
214
229
defer r .mu .Unlock ()
215
- delete (r .operators , name )
230
+ delete (r .lastResourceVersion , name )
216
231
}
217
232
218
- func (r * OperatorReconciler ) mapComponentRequests (obj handler.MapObject ) (requests []reconcile.Request ) {
233
+ func (r * OperatorReconciler ) mapComponentRequests (obj handler.MapObject ) []reconcile.Request {
234
+ var requests []reconcile.Request
219
235
if obj .Meta == nil {
220
- return
236
+ return requests
221
237
}
222
238
223
239
for _ , name := range decorators .OperatorNames (obj .Meta .GetLabels ()) {
224
- // Only enqueue if we can find the operator in our cache
225
- if r .observed (name ) {
226
- requests = append (requests , reconcile.Request {NamespacedName : name })
227
- continue
228
- }
229
-
230
- // Otherwise, best-effort generate a new operator
231
- // TODO(njhale): Implement verification that the operator-discovery admission webhook accepted this label (JWT or maybe sign a set of fields?)
232
- operator := & operatorsv1.Operator {}
233
- operator .SetName (name .Name )
234
- if err := r .Create (context .Background (), operator ); err != nil && ! apierrors .IsAlreadyExists (err ) {
235
- r .log .Error (err , "couldn't generate operator" , "operator" , name , "component" , obj .Meta .GetSelfLink ())
236
- }
240
+ // unset the last recorded resource version so the Operator will reconcile
241
+ r .unsetLastResourceVersion (name )
242
+ requests = append (requests , reconcile.Request {NamespacedName : name })
237
243
}
238
244
239
- return
245
+ return requests
240
246
}
0 commit comments