Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 76 additions & 28 deletions controllers/operatorchecker/operatorchecker_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
package operatorchecker

import (
"fmt"
"time"
"errors"
"context"
"strings"

olmv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/klog"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -48,43 +52,87 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re
if _, ok := subscriptionInstance.Labels[constant.OpreqLabel]; !ok {
return
}
if subscriptionInstance.Status.State != "" {
return
}
for _, condition := range subscriptionInstance.Status.Conditions {
if condition.Type == "ResolutionFailed" && condition.Reason == "ConstraintsNotSatisfiable" {
csvList := &olmv1alpha1.ClusterServiceVersionList{}
opts := []client.ListOption{
client.InNamespace(subscriptionInstance.Namespace),
}
if err := r.Client.List(ctx, csvList, opts...); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)

if subscriptionInstance.Status.CurrentCSV == "" && subscriptionInstance.Status.State == "" {
// cover fresh install case
csv, err := r.getCSVBySubscription(ctx, subscriptionInstance)
if err != nil {
// not found csv
klog.Error(err)
return
}
err = wait.PollImmediate(time.Second*3, time.Minute*1, func() (bool, error) {
if subscriptionInstance.Status.CurrentCSV == "" && subscriptionInstance.Status.State == "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to fetch the subscription again here to get the latest status information.

return false, nil
}
return true, nil
})
if subscriptionInstance.Status.CurrentCSV == "" && subscriptionInstance.Status.State == "" {
r.deleteCSV(ctx, csv.Name, csv.Namespace)
}
}

for _, csv := range csvList.Items {
if strings.Contains(csv.Name, subscriptionInstance.Name) {
if csv.Status.Phase == "Succeeded" {
csvInstance := &olmv1alpha1.ClusterServiceVersion{}
csvKey := types.NamespacedName{
Name: csv.Name,
Namespace: csv.Namespace,
}
if err := r.Client.Get(ctx, csvKey, csvInstance); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
if err := r.Client.Delete(ctx, csvInstance); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
}
break
if subscriptionInstance.Status.CurrentCSV != "" && subscriptionInstance.Status.State == "UpgradePending" {
// cover upgrade case
csv, err := r.getCSVBySubscription(ctx, subscriptionInstance)
if err != nil {
// get multi versions of CSV
klog.Error(err)
return
}
if subscriptionInstance.Status.CurrentCSV != fmt.Sprintf("%v", csv.Spec.Version) {
err = wait.PollImmediate(time.Second*3, time.Minute*1, func() (bool, error) {
if subscriptionInstance.Status.CurrentCSV != "" && subscriptionInstance.Status.State == "UpgradePending" {
return false, nil
}
return true, nil
})
if subscriptionInstance.Status.CurrentCSV != "" && subscriptionInstance.Status.State == "UpgradePending" {
r.deleteCSV(ctx, csv.Name, csv.Namespace)
}
break
}
}

return ctrl.Result{RequeueAfter: constant.DefaultRequeueDuration}, nil
}

func (r *Reconciler) getCSVBySubscription(ctx context.Context, subscriptionInstance *olmv1alpha1.Subscription) (*olmv1alpha1.ClusterServiceVersion, error) {
csvList := &olmv1alpha1.ClusterServiceVersionList{}
opts := []client.ListOption{
client.InNamespace(subscriptionInstance.Namespace),
}
if err := r.Client.List(ctx, csvList, opts...); err != nil {
return nil, client.IgnoreNotFound(err)
}

var matchCSVList = []olmv1alpha1.ClusterServiceVersion{}
for _, csv := range csvList.Items {
if strings.Contains(csv.Name, subscriptionInstance.Name) {
matchCSVList = append(matchCSVList, csv)
}
}

if len(matchCSVList) == 1 {
return &matchCSVList[0], nil
}
return nil, errors.New("Fail to find matched CSV")
}

func (r *Reconciler) deleteCSV(ctx context.Context, name, namespace string) error {
csvInstance := &olmv1alpha1.ClusterServiceVersion{}
csvKey := types.NamespacedName{
Name: name,
Namespace: namespace,
}
if err := r.Client.Get(ctx, csvKey, csvInstance); err != nil {
return client.IgnoreNotFound(err)
}
if err := r.Client.Delete(ctx, csvInstance); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can just use the delete command

return client.IgnoreNotFound(err)
}
return nil
}

// SetupWithManager adds subscription to watch to the manager.
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
Expand Down