Skip to content

Commit d4a3db0

Browse files
authored
Find CSVs by label for an operator, to ensure deleting all the CSVs for a specific subscription (#1055)
* Find CSVs by label for an operator, to ensure deleting all the CSVs for a specific subscription Signed-off-by: Daniel Fan <[email protected]> * Update test case Signed-off-by: Daniel Fan <[email protected]> --------- Signed-off-by: Daniel Fan <[email protected]>
1 parent 13d2591 commit d4a3db0

File tree

6 files changed

+76
-29
lines changed

6 files changed

+76
-29
lines changed

controllers/operandconfig/operandconfig_controller_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,15 @@ var _ = Describe("OperandConfig controller", func() {
121121
}, timeout, interval).Should(Succeed())
122122

123123
By("Creating and Setting status of the ClusterServiceVersions")
124-
jaegerCSV := testutil.ClusterServiceVersion("jaeger-csv.v0.0.1", operatorNamespaceName, testutil.JaegerExample)
124+
jaegerCSV := testutil.ClusterServiceVersion("jaeger-csv.v0.0.1", "jaeger", operatorNamespaceName, testutil.JaegerExample)
125125
Expect(k8sClient.Create(ctx, jaegerCSV)).Should(Succeed())
126126
Eventually(func() error {
127127
k8sClient.Get(ctx, types.NamespacedName{Name: "jaeger-csv.v0.0.1", Namespace: operatorNamespaceName}, jaegerCSV)
128128
jaegerCSV.Status = testutil.ClusterServiceVersionStatus()
129129
return k8sClient.Status().Update(ctx, jaegerCSV)
130130
}, timeout, interval).Should(Succeed())
131131

132-
mongodbCSV := testutil.ClusterServiceVersion("mongodb-atlas-kubernetes-csv.v0.0.1", operatorNamespaceName, testutil.MongodbExample)
132+
mongodbCSV := testutil.ClusterServiceVersion("mongodb-atlas-kubernetes-csv.v0.0.1", "mongodb-atlas-kubernetes", operatorNamespaceName, testutil.MongodbExample)
133133
Expect(k8sClient.Create(ctx, mongodbCSV)).Should(Succeed())
134134
Eventually(func() error {
135135
k8sClient.Get(ctx, types.NamespacedName{Name: "mongodb-atlas-kubernetes-csv.v0.0.1", Namespace: operatorNamespaceName}, mongodbCSV)

controllers/operandregistry/operandregistry_controller_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,15 @@ var _ = Describe("OperandRegistry controller", func() {
120120
}, timeout, interval).Should(Succeed())
121121

122122
By("Creating and Setting status of the ClusterServiceVersions")
123-
jaegerCSV := testutil.ClusterServiceVersion("jaeger-csv.v0.0.1", operatorNamespaceName, testutil.JaegerExample)
123+
jaegerCSV := testutil.ClusterServiceVersion("jaeger-csv.v0.0.1", "jaeger", operatorNamespaceName, testutil.JaegerExample)
124124
Expect(k8sClient.Create(ctx, jaegerCSV)).Should(Succeed())
125125
Eventually(func() error {
126126
k8sClient.Get(ctx, types.NamespacedName{Name: "jaeger-csv.v0.0.1", Namespace: operatorNamespaceName}, jaegerCSV)
127127
jaegerCSV.Status = testutil.ClusterServiceVersionStatus()
128128
return k8sClient.Status().Update(ctx, jaegerCSV)
129129
}, timeout, interval).Should(Succeed())
130130

131-
mongodbCSV := testutil.ClusterServiceVersion("mongodb-atlas-kubernetes-csv.v0.0.1", operatorNamespaceName, testutil.MongodbExample)
131+
mongodbCSV := testutil.ClusterServiceVersion("mongodb-atlas-kubernetes-csv.v0.0.1", "mongodb-atlas-kubernetes", operatorNamespaceName, testutil.MongodbExample)
132132
Expect(k8sClient.Create(ctx, mongodbCSV)).Should(Succeed())
133133
Eventually(func() error {
134134
k8sClient.Get(ctx, types.NamespacedName{Name: "mongodb-atlas-kubernetes-csv.v0.0.1", Namespace: operatorNamespaceName}, mongodbCSV)

controllers/operandrequest/operandrequest_controller_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,15 +140,15 @@ var _ = Describe("OperandRequest controller", func() {
140140
}, testutil.Timeout, testutil.Interval).Should(Succeed())
141141

142142
By("Creating and Setting status of the ClusterServiceVersions")
143-
jaegerCSV := testutil.ClusterServiceVersion("jaeger-csv.v0.0.1", operatorNamespaceName, testutil.JaegerExample)
143+
jaegerCSV := testutil.ClusterServiceVersion("jaeger-csv.v0.0.1", "jaeger", operatorNamespaceName, testutil.JaegerExample)
144144
Expect(k8sClient.Create(ctx, jaegerCSV)).Should(Succeed())
145145
Eventually(func() error {
146146
k8sClient.Get(ctx, types.NamespacedName{Name: "jaeger-csv.v0.0.1", Namespace: operatorNamespaceName}, jaegerCSV)
147147
jaegerCSV.Status = testutil.ClusterServiceVersionStatus()
148148
return k8sClient.Status().Update(ctx, jaegerCSV)
149149
}, testutil.Timeout, testutil.Interval).Should(Succeed())
150150

151-
mongodbCSV := testutil.ClusterServiceVersion("mongodb-atlas-kubernetes-csv.v0.0.1", operatorNamespaceName, testutil.MongodbExample)
151+
mongodbCSV := testutil.ClusterServiceVersion("mongodb-atlas-kubernetes-csv.v0.0.1", "mongodb-atlas-kubernetes", operatorNamespaceName, testutil.MongodbExample)
152152
Expect(k8sClient.Create(ctx, mongodbCSV)).Should(Succeed())
153153
Eventually(func() error {
154154
k8sClient.Get(ctx, types.NamespacedName{Name: "mongodb-atlas-kubernetes-csv.v0.0.1", Namespace: operatorNamespaceName}, mongodbCSV)
@@ -272,15 +272,15 @@ var _ = Describe("OperandRequest controller", func() {
272272
}, testutil.Timeout, testutil.Interval).Should(Succeed())
273273

274274
By("Creating and Setting status of the ClusterServiceVersions")
275-
jaegerCSV := testutil.ClusterServiceVersion("jaeger-csv.v0.0.1", operatorNamespaceName, testutil.JaegerExample)
275+
jaegerCSV := testutil.ClusterServiceVersion("jaeger-csv.v0.0.1", "jaeger", operatorNamespaceName, testutil.JaegerExample)
276276
Expect(k8sClient.Create(ctx, jaegerCSV)).Should(Succeed())
277277
Eventually(func() error {
278278
k8sClient.Get(ctx, types.NamespacedName{Name: "jaeger-csv.v0.0.1", Namespace: operatorNamespaceName}, jaegerCSV)
279279
jaegerCSV.Status = testutil.ClusterServiceVersionStatus()
280280
return k8sClient.Status().Update(ctx, jaegerCSV)
281281
}, testutil.Timeout, testutil.Interval).Should(Succeed())
282282

283-
mongodbCSV := testutil.ClusterServiceVersion("mongodb-atlas-kubernetes-csv.v0.0.1", operatorNamespaceName, testutil.MongodbExample)
283+
mongodbCSV := testutil.ClusterServiceVersion("mongodb-atlas-kubernetes-csv.v0.0.1", "mongodb-atlas-kubernetes", operatorNamespaceName, testutil.MongodbExample)
284284
Expect(k8sClient.Create(ctx, mongodbCSV)).Should(Succeed())
285285
Eventually(func() error {
286286
k8sClient.Get(ctx, types.NamespacedName{Name: "mongodb-atlas-kubernetes-csv.v0.0.1", Namespace: operatorNamespaceName}, mongodbCSV)
@@ -433,15 +433,15 @@ var _ = Describe("OperandRequest controller", func() {
433433
}, testutil.Timeout, testutil.Interval).Should(Succeed())
434434

435435
By("Creating and Setting status of the ClusterServiceVersions")
436-
jaegerCSV := testutil.ClusterServiceVersion("jaeger-csv.v0.0.1", operatorNamespaceName, testutil.JaegerExample)
436+
jaegerCSV := testutil.ClusterServiceVersion("jaeger-csv.v0.0.1", "jaeger", operatorNamespaceName, testutil.JaegerExample)
437437
Expect(k8sClient.Create(ctx, jaegerCSV)).Should(Succeed())
438438
Eventually(func() error {
439439
k8sClient.Get(ctx, types.NamespacedName{Name: "jaeger-csv.v0.0.1", Namespace: operatorNamespaceName}, jaegerCSV)
440440
jaegerCSV.Status = testutil.ClusterServiceVersionStatus()
441441
return k8sClient.Status().Update(ctx, jaegerCSV)
442442
}, testutil.Timeout, testutil.Interval).Should(Succeed())
443443

444-
mongodbCSV := testutil.ClusterServiceVersion("mongodb-atlas-kubernetes-csv.v0.0.1", operatorNamespaceName, testutil.MongodbExample)
444+
mongodbCSV := testutil.ClusterServiceVersion("mongodb-atlas-kubernetes-csv.v0.0.1", "mongodb-atlas-kubernetes", operatorNamespaceName, testutil.MongodbExample)
445445
Expect(k8sClient.Create(ctx, mongodbCSV)).Should(Succeed())
446446
Eventually(func() error {
447447
k8sClient.Get(ctx, types.NamespacedName{Name: "mongodb-atlas-kubernetes-csv.v0.0.1", Namespace: operatorNamespaceName}, mongodbCSV)

controllers/operandrequest/reconcile_operator.go

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -351,20 +351,23 @@ func (r *Reconciler) deleteSubscription(ctx context.Context, cr *operatorv1alpha
351351

352352
klog.V(2).Infof("Deleting Subscription %s/%s ...", sub.Namespace, sub.Name)
353353

354-
csv, err := r.GetClusterServiceVersion(ctx, sub)
354+
csvList, err := r.GetClusterServiceVersionList(ctx, sub)
355355
// If can't get CSV, requeue the request
356356
if err != nil {
357357
return err
358358
}
359359

360-
if csv != nil {
361-
klog.V(3).Info("Set Deleting Condition in the operandRequest")
362-
cr.SetDeletingCondition(csv.Name, operatorv1alpha1.ResourceTypeCsv, corev1.ConditionTrue, &r.Mutex)
360+
if csvList != nil {
361+
klog.Infof("Found %d ClusterServiceVersions for Subscription %s/%s", len(csvList), sub.Namespace, sub.Name)
362+
for _, csv := range csvList {
363+
klog.V(3).Info("Set Deleting Condition in the operandRequest")
364+
cr.SetDeletingCondition(csv.Name, operatorv1alpha1.ResourceTypeCsv, corev1.ConditionTrue, &r.Mutex)
363365

364-
klog.V(1).Infof("Deleting the ClusterServiceVersion, Namespace: %s, Name: %s", csv.Namespace, csv.Name)
365-
if err := r.Delete(ctx, csv); err != nil {
366-
cr.SetDeletingCondition(csv.Name, operatorv1alpha1.ResourceTypeCsv, corev1.ConditionFalse, &r.Mutex)
367-
return err
366+
klog.V(1).Infof("Deleting the ClusterServiceVersion, Namespace: %s, Name: %s", csv.Namespace, csv.Name)
367+
if err := r.Delete(ctx, csv); err != nil {
368+
cr.SetDeletingCondition(csv.Name, operatorv1alpha1.ResourceTypeCsv, corev1.ConditionFalse, &r.Mutex)
369+
return err
370+
}
368371
}
369372
}
370373

@@ -426,16 +429,17 @@ func (r *Reconciler) uninstallOperatorsAndOperands(ctx context.Context, operandN
426429
return nil
427430
}
428431

429-
if csv, err := r.GetClusterServiceVersion(ctx, sub); err != nil {
432+
if csvList, err := r.GetClusterServiceVersionList(ctx, sub); err != nil {
430433
// If can't get CSV, requeue the request
431434
return err
432-
} else if csv != nil {
435+
} else if csvList != nil {
436+
klog.Infof("Found %d ClusterServiceVersions for Subscription %s/%s", len(csvList), sub.Namespace, sub.Name)
433437
if uninstallOperand {
434-
klog.V(2).Infof("Deleting all the Custom Resources for CSV, Namespace: %s, Name: %s", csv.Namespace, csv.Name)
435-
if err := r.deleteAllCustomResource(ctx, csv, requestInstance, configInstance, operandName, configInstance.Namespace); err != nil {
438+
klog.V(2).Infof("Deleting all the Custom Resources for CSV, Namespace: %s, Name: %s", csvList[0].Namespace, csvList[0].Name)
439+
if err := r.deleteAllCustomResource(ctx, csvList[0], requestInstance, configInstance, operandName, configInstance.Namespace); err != nil {
436440
return err
437441
}
438-
klog.V(2).Infof("Deleting all the k8s Resources for CSV, Namespace: %s, Name: %s", csv.Namespace, csv.Name)
442+
klog.V(2).Infof("Deleting all the k8s Resources for CSV, Namespace: %s, Name: %s", csvList[0].Namespace, csvList[0].Name)
439443
if err := r.deleteAllK8sResource(ctx, configInstance, operandName, configInstance.Namespace); err != nil {
440444
return err
441445
}
@@ -447,12 +451,14 @@ func (r *Reconciler) uninstallOperatorsAndOperands(ctx context.Context, operandN
447451
}
448452

449453
klog.V(3).Info("Set Deleting Condition in the operandRequest")
450-
requestInstance.SetDeletingCondition(csv.Name, operatorv1alpha1.ResourceTypeCsv, corev1.ConditionTrue, &r.Mutex)
454+
requestInstance.SetDeletingCondition(csvList[0].Name, operatorv1alpha1.ResourceTypeCsv, corev1.ConditionTrue, &r.Mutex)
451455

452-
klog.V(1).Infof("Deleting the ClusterServiceVersion, Namespace: %s, Name: %s", csv.Namespace, csv.Name)
453-
if err := r.Delete(ctx, csv); err != nil {
454-
requestInstance.SetDeletingCondition(csv.Name, operatorv1alpha1.ResourceTypeCsv, corev1.ConditionFalse, &r.Mutex)
455-
return errors.Wrap(err, "failed to delete the ClusterServiceVersion")
456+
for _, csv := range csvList {
457+
klog.V(1).Infof("Deleting the ClusterServiceVersion, Namespace: %s, Name: %s", csv.Namespace, csv.Name)
458+
if err := r.Delete(ctx, csv); err != nil {
459+
requestInstance.SetDeletingCondition(csv.Name, operatorv1alpha1.ResourceTypeCsv, corev1.ConditionFalse, &r.Mutex)
460+
return errors.Wrapf(err, "failed to delete the ClusterServiceVersion %s/%s", csv.Namespace, csv.Name)
461+
}
456462
}
457463
}
458464
}

controllers/operator/manager.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,44 @@ func (m *ODLMOperator) GetClusterServiceVersion(ctx context.Context, sub *olmv1a
391391
return csv, nil
392392
}
393393

394+
// GetClusterServiceVersionList gets a list of ClusterServiceVersions from the subscription
395+
func (m *ODLMOperator) GetClusterServiceVersionList(ctx context.Context, sub *olmv1alpha1.Subscription) ([]*olmv1alpha1.ClusterServiceVersion, error) {
396+
// Check if subscription is nil
397+
if sub == nil {
398+
klog.Error("The subscription is nil")
399+
return nil, fmt.Errorf("the subscription is nil")
400+
}
401+
402+
packageName := sub.Spec.Package
403+
csvNamespace := sub.Namespace
404+
405+
// Get the ClusterServiceVersion list with label operators.coreos.com/packageName.csvNamespace=''
406+
csvList := &olmv1alpha1.ClusterServiceVersionList{}
407+
opts := []client.ListOption{
408+
client.MatchingLabels{fmt.Sprintf("operators.coreos.com/%s.%s", packageName, csvNamespace): ""},
409+
client.InNamespace(csvNamespace),
410+
}
411+
412+
if err := m.Reader.List(ctx, csvList, opts...); err != nil {
413+
if apierrors.IsNotFound(err) || len(csvList.Items) == 0 {
414+
klog.V(3).Infof("No ClusterServiceVersion found with label operators.coreos.com/%s.%s", packageName, csvNamespace)
415+
return nil, nil
416+
}
417+
return nil, errors.Wrapf(err, "failed to list ClusterServiceVersions with label operators.coreos.com/%s.%s", packageName, csvNamespace)
418+
} else if len(csvList.Items) > 1 {
419+
klog.Warningf("Multiple ClusterServiceVersions found with label operators.coreos.com/%s.%s", packageName, csvNamespace)
420+
}
421+
422+
var csvs []*olmv1alpha1.ClusterServiceVersion
423+
for i := range csvList.Items {
424+
klog.V(3).Infof("Get ClusterServiceVersion %s in the namespace %s", csvList.Items[i].Name, csvNamespace)
425+
csvs = append(csvs, &csvList.Items[i])
426+
}
427+
428+
klog.V(3).Infof("Get %v ClusterServiceVersions in the namespace %s", len(csvs), csvNamespace)
429+
return csvs, nil
430+
}
431+
394432
// GetOperatorNamespace returns the operator namespace based on the install mode
395433
func (m *ODLMOperator) GetOperatorNamespace(installMode, namespace string) string {
396434
if installMode == apiv1alpha1.InstallModeCluster {

controllers/testutil/test_util.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,14 +495,17 @@ func SubscriptionStatus(name, namespace, csvVersion string) olmv1alpha1.Subscrip
495495
}
496496
}
497497

498-
func ClusterServiceVersion(name, namespace, example string) *olmv1alpha1.ClusterServiceVersion {
498+
func ClusterServiceVersion(name, packageName, namespace, example string) *olmv1alpha1.ClusterServiceVersion {
499499
return &olmv1alpha1.ClusterServiceVersion{
500500
ObjectMeta: metav1.ObjectMeta{
501501
Name: name,
502502
Namespace: namespace,
503503
Annotations: map[string]string{
504504
"alm-examples": example,
505505
},
506+
Labels: map[string]string{
507+
"operators.coreos.com/" + packageName + "." + namespace: "",
508+
},
506509
},
507510
Spec: olmv1alpha1.ClusterServiceVersionSpec{
508511
InstallStrategy: olmv1alpha1.NamedInstallStrategy{

0 commit comments

Comments
 (0)