@@ -2,7 +2,6 @@ package operators
2
2
3
3
import (
4
4
"context"
5
- "fmt"
6
5
"sync"
7
6
8
7
"github.com/go-logr/logr"
@@ -54,6 +53,7 @@ func (r *AdoptionReconciler) SetupWithManager(mgr ctrl.Manager) error {
54
53
err := ctrl .NewControllerManagedBy (mgr ).
55
54
For (& operatorsv1alpha1.Subscription {}).
56
55
Watches (& source.Kind {Type : & operatorsv1alpha1.ClusterServiceVersion {}}, enqueueSub ).
56
+ Watches (& source.Kind {Type : & operatorsv1alpha1.InstallPlan {}}, enqueueSub ).
57
57
Complete (reconcile .Func (r .ReconcileSubscription ))
58
58
if err != nil {
59
59
return err
@@ -77,7 +77,6 @@ func (r *AdoptionReconciler) SetupWithManager(mgr ctrl.Manager) error {
77
77
Watches (& source.Kind {Type : & apiextensionsv1.CustomResourceDefinition {}}, enqueueCSV ).
78
78
Watches (& source.Kind {Type : & apiregistrationv1.APIService {}}, enqueueCSV ).
79
79
Watches (& source.Kind {Type : & operatorsv1alpha1.Subscription {}}, enqueueCSV ).
80
- Watches (& source.Kind {Type : & operatorsv1alpha1.InstallPlan {}}, enqueueCSV ).
81
80
Complete (reconcile .Func (r .ReconcileClusterServiceVersion ))
82
81
if err != nil {
83
82
return err
@@ -107,8 +106,6 @@ func NewAdoptionReconciler(cli client.Client, log logr.Logger, scheme *runtime.S
107
106
}, nil
108
107
}
109
108
110
- var fieldOwner = client .FieldOwner ("olm" )
111
-
112
109
// ReconcileSubscription labels the CSVs installed by a Subscription as components of an operator named after the subscribed package and install namespace.
113
110
func (r * AdoptionReconciler ) ReconcileSubscription (req ctrl.Request ) (reconcile.Result , error ) {
114
111
// Set up a convenient log object so we don't have to type request over and over again
@@ -141,51 +138,30 @@ func (r *AdoptionReconciler) ReconcileSubscription(req ctrl.Request) (reconcile.
141
138
return reconcile.Result {}, nil
142
139
}
143
140
144
- // Ensure the subscription is adopted
141
+ // Adopt the Subscription
145
142
var errs []error
146
- out := in .DeepCopy ()
147
- adopted , err := operator .AdoptComponent (out )
148
- if err != nil {
143
+ if err := r .adopt (ctx , operator , in ); err != nil {
144
+ log .Error (err , "Error adopting Subscription" )
149
145
errs = append (errs , err )
150
146
}
151
- if adopted {
152
- if err := r .Patch (ctx , out , client .MergeFrom (in )); err != nil {
153
- log .Error (err , "Error adopting Subscription" )
154
- errs = append (errs , err )
155
- }
156
- }
157
147
158
- // Find the Subscription's CSVs and apply the component label if necessary
159
- adoptCSV := func ( name string ) error {
148
+ // Adopt the Subscription's installed CSV
149
+ if name := in . Status . InstalledCSV ; name != "" {
160
150
csv := & operatorsv1alpha1.ClusterServiceVersion {}
161
- if err := r .Get (ctx , types.NamespacedName {Namespace : in .GetNamespace (), Name : name }, csv ); err != nil {
162
- if apierrors .IsNotFound (err ) {
163
- err = nil
164
- }
165
-
166
- return err
167
- }
168
- log .Info ("found CSV" )
169
-
170
- candidate := csv .DeepCopy ()
171
- adopted , err := operator .AdoptComponent (csv )
172
- if err != nil {
173
- return err
174
- }
175
-
176
- if adopted {
177
- // Only update the CSV if freshly adopted
178
- if err := r .Patch (ctx , csv , client .MergeFrom (candidate )); err != nil {
179
- return err
180
- }
151
+ csv .SetNamespace (in .GetNamespace ())
152
+ csv .SetName (name )
153
+ if err := r .adopt (ctx , operator , csv ); err != nil {
154
+ log .Error (err , "Error adopting installed CSV" )
155
+ errs = append (errs , err )
181
156
}
182
-
183
- return nil
184
157
}
185
158
186
- if name := in .Status .InstalledCSV ; name != "" {
187
- if err := adoptCSV (name ); err != nil {
188
- log .Error (err , "Error adopting installed CSV" )
159
+ // Adopt the Subscription's latest InstallPlan and Disown all others in the same namespace
160
+ if ref := in .Status .InstallPlanRef ; ref != nil {
161
+ ip := & operatorsv1alpha1.InstallPlan {}
162
+ ip .SetNamespace (ref .Namespace )
163
+ ip .SetName (ref .Name )
164
+ if err := r .adoptInstallPlan (ctx , operator , ip ); err != nil {
189
165
errs = append (errs , err )
190
166
}
191
167
}
@@ -204,12 +180,12 @@ func (r *AdoptionReconciler) ReconcileClusterServiceVersion(req ctrl.Request) (r
204
180
in := & operatorsv1alpha1.ClusterServiceVersion {}
205
181
if err := r .Get (ctx , req .NamespacedName , in ); err != nil {
206
182
if apierrors .IsNotFound (err ) {
207
- log . Info ( "Could not find ClusterServiceVersion" )
183
+ err = nil
208
184
} else {
209
185
log .Error (err , "Error finding ClusterServiceVersion" )
210
186
}
211
187
212
- return reconcile.Result {}, nil
188
+ return reconcile.Result {}, err
213
189
}
214
190
215
191
// Adopt all resources owned by the CSV if necessary
@@ -239,38 +215,90 @@ func (r *AdoptionReconciler) adoptComponents(ctx context.Context, csv *operators
239
215
}
240
216
241
217
// Label (adopt) prospective components
242
- var errs []error
243
- // TODO(njhale): parallelize
218
+ var (
219
+ errs []error
220
+ mu sync.Mutex
221
+ wg sync.WaitGroup
222
+ )
244
223
for _ , operator := range operators {
245
224
components , err := r .adoptees (ctx , operator , csv )
246
225
if err != nil {
247
- errs = append (errs , err )
226
+ func () {
227
+ mu .Lock ()
228
+ defer mu .Unlock ()
229
+ errs = append (errs , err )
230
+ }()
248
231
continue
249
232
}
250
233
251
234
for _ , component := range components {
252
- candidate := component .DeepCopyObject ()
253
- adopted , err := operator .AdoptComponent (component )
254
- if err != nil {
255
- errs = append (errs , err )
256
- continue
257
- }
235
+ var (
236
+ // Copy variables into iteration scope
237
+ operator = operator
238
+ component = component
239
+ )
240
+ wg .Add (1 )
241
+
242
+ go func () {
243
+ defer wg .Done ()
244
+ if err := r .adopt (ctx , & operator , component ); err != nil {
245
+ mu .Lock ()
246
+ defer mu .Unlock ()
247
+ errs = append (errs , err )
248
+ }
249
+ }()
250
+ }
251
+ }
252
+ wg .Wait ()
258
253
259
- if ! adopted {
260
- // Don't update since we didn't adopt
261
- // This shouldn't occur since we already filtered candidates
262
- r .log .Error (fmt .Errorf ("failed to adopt component candidate" ), "candidate not adopted" , "candidate" , component )
263
- continue
264
- }
254
+ return utilerrors .NewAggregate (errs )
255
+ }
265
256
266
- // Patch the component to adopt
267
- if err = r .Patch (ctx , component , client .MergeFrom (candidate )); err != nil {
268
- errs = append (errs , err )
269
- }
257
+ func (r * AdoptionReconciler ) adopt (ctx context.Context , operator * decorators.Operator , component runtime.Object ) error {
258
+ m , err := meta .Accessor (component )
259
+ if err != nil {
260
+ return nil
261
+ }
262
+
263
+ if err := r .Get (ctx , types.NamespacedName {Namespace : m .GetNamespace (), Name : m .GetName ()}, component ); err != nil {
264
+ if apierrors .IsNotFound (err ) {
265
+ r .log .Error (err , "component not found" )
266
+ err = nil
270
267
}
268
+
269
+ return err
271
270
}
271
+ candidate := component .DeepCopyObject ()
272
272
273
- return utilerrors .NewAggregate (errs )
273
+ adopted , err := operator .AdoptComponent (candidate )
274
+ if err != nil {
275
+ return err
276
+ }
277
+
278
+ if adopted {
279
+ // Only update if freshly adopted
280
+ r .log .Info ("component adopted" , "component" , candidate )
281
+ return r .Patch (ctx , candidate , client .MergeFrom (component ))
282
+ }
283
+
284
+ return nil
285
+ }
286
+
287
+ func (r * AdoptionReconciler ) disown (ctx context.Context , operator * decorators.Operator , component runtime.Object ) error {
288
+ candidate := component .DeepCopyObject ()
289
+ disowned , err := operator .DisownComponent (candidate )
290
+ if err != nil {
291
+ return err
292
+ }
293
+
294
+ if ! disowned {
295
+ // Wasn't a component
296
+ return nil
297
+ }
298
+
299
+ // Only update if freshly disowned
300
+ r .log .V (4 ).Info ("component disowned" , "component" , candidate )
301
+ return r .Patch (ctx , candidate , client .MergeFrom (component ))
274
302
}
275
303
276
304
func (r * AdoptionReconciler ) adoptees (ctx context.Context , operator decorators.Operator , csv * operatorsv1alpha1.ClusterServiceVersion ) ([]runtime.Object , error ) {
@@ -350,6 +378,41 @@ func (r *AdoptionReconciler) adoptees(ctx context.Context, operator decorators.O
350
378
return components , nil
351
379
}
352
380
381
+ func (r * AdoptionReconciler ) adoptInstallPlan (ctx context.Context , operator * decorators.Operator , latest * operatorsv1alpha1.InstallPlan ) error {
382
+ // Adopt the latest InstallPlan
383
+ if err := r .adopt (ctx , operator , latest ); err != nil {
384
+ return err
385
+ }
386
+
387
+ // Disown older InstallPlans
388
+ selector , err := operator .ComponentSelector ()
389
+ if err != nil {
390
+ return err
391
+ }
392
+
393
+ var (
394
+ ips = & operatorsv1alpha1.InstallPlanList {}
395
+ opt = client.MatchingLabelsSelector {Selector : selector }
396
+ )
397
+ if err := r .List (ctx , ips , opt , client .InNamespace (latest .GetNamespace ())); err != nil {
398
+ return err
399
+ }
400
+
401
+ var errs []error
402
+ for _ , ip := range ips .Items {
403
+ if ip .GetName () == latest .GetName () {
404
+ // Don't disown latest
405
+ continue
406
+ }
407
+
408
+ if err := r .disown (ctx , operator , & ip ); err != nil {
409
+ errs = append (errs , err )
410
+ }
411
+ }
412
+
413
+ return utilerrors .NewAggregate (errs )
414
+ }
415
+
353
416
func (r * AdoptionReconciler ) mapToSubscriptions (obj handler.MapObject ) (requests []reconcile.Request ) {
354
417
if obj .Meta == nil {
355
418
return
@@ -367,7 +430,6 @@ func (r *AdoptionReconciler) mapToSubscriptions(obj handler.MapObject) (requests
367
430
nsn := types.NamespacedName {Namespace : sub .GetNamespace (), Name : sub .GetName ()}
368
431
requests = append (requests , reconcile.Request {NamespacedName : nsn })
369
432
}
370
- r .log .Info ("requeueing subscriptions" , "requests" , requests )
371
433
372
434
return
373
435
}
0 commit comments