github.com/operator-framework/operator-lifecycle-manager@v0.30.0/pkg/lib/csv/replace_finder.go (about) 1 package csv 2 3 import ( 4 "context" 5 6 "github.com/sirupsen/logrus" 7 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 9 "github.com/operator-framework/api/pkg/operators/v1alpha1" 10 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned" 11 ) 12 13 // NewReplaceFinder returns an instance of ReplaceFinder 14 func NewReplaceFinder(logger *logrus.Logger, client versioned.Interface) ReplaceFinder { 15 return &replace{ 16 logger: logger, 17 client: client, 18 } 19 } 20 21 // ReplaceFinder is an interface that finds the next or previous 22 // ClusterServiceVersion object in the upgrade path for a given CSV. 23 type ReplaceFinder interface { 24 IsBeingReplaced(in *v1alpha1.ClusterServiceVersion, csvsInNamespace map[string]*v1alpha1.ClusterServiceVersion) (replacedBy *v1alpha1.ClusterServiceVersion) 25 IsReplacing(in *v1alpha1.ClusterServiceVersion) *v1alpha1.ClusterServiceVersion 26 GetFinalCSVInReplacing(in *v1alpha1.ClusterServiceVersion, csvsInNamespace map[string]*v1alpha1.ClusterServiceVersion) (replacedBy *v1alpha1.ClusterServiceVersion) 27 } 28 29 type replace struct { 30 logger *logrus.Logger 31 client versioned.Interface 32 } 33 34 // IsBeingReplaced returns the corresponding ClusterServiceVersion object that 35 // is replacing the given CSV specified. 36 // 37 // If the corresponding ClusterServiceVersion is not found nil is returned. 38 func (r *replace) IsBeingReplaced(in *v1alpha1.ClusterServiceVersion, csvsInNamespace map[string]*v1alpha1.ClusterServiceVersion) (replacedBy *v1alpha1.ClusterServiceVersion) { 39 for _, csv := range csvsInNamespace { 40 if csv.IsCopied() { 41 continue 42 } 43 44 r.logger.Debugf("checking %s", csv.GetName()) 45 46 if csv.Spec.Replaces == in.GetName() { 47 r.logger.Infof("%s replaced by %s", in.GetName(), csv.GetName()) 48 replacedBy = csv 49 return 50 } 51 } 52 53 return 54 } 55 56 // IsReplacing returns the corresponding ClusterServiceVersion object that the 57 // given CSV specified replaces. 58 // 59 // If the corresponding ClusterServiceVersion is not found nil is returned. 60 func (r *replace) IsReplacing(in *v1alpha1.ClusterServiceVersion) *v1alpha1.ClusterServiceVersion { 61 r.logger.Debugf("checking if csv is replacing an older version") 62 if in.Spec.Replaces == "" { 63 return nil 64 } 65 66 // using the client instead of a lister; missing an object because of a cache sync can cause upgrades to fail 67 previous, err := r.client.OperatorsV1alpha1().ClusterServiceVersions(in.GetNamespace()).Get(context.TODO(), in.Spec.Replaces, metav1.GetOptions{}) 68 if err != nil { 69 r.logger.WithField("replacing", in.Spec.Replaces).WithError(err).Debugf("unable to get previous csv") 70 return nil 71 } 72 73 return previous 74 } 75 76 // GetFinalCSVInReplacing returns the most recent ClustererviceVersion that is 77 // in the replace chain. 78 // 79 // If the corresponding ClusterServiceVersion is not found nil is returned. 80 func (r *replace) GetFinalCSVInReplacing(in *v1alpha1.ClusterServiceVersion, csvsInNamespace map[string]*v1alpha1.ClusterServiceVersion) (replacedBy *v1alpha1.ClusterServiceVersion) { 81 current := in 82 for { 83 next := r.IsBeingReplaced(current, csvsInNamespace) 84 if next == nil { 85 break 86 } 87 88 replacedBy = next 89 current = next 90 } 91 92 return 93 }