@@ -5,10 +5,12 @@ import (
55 "sort"
66
77 mmsemver "github.com/Masterminds/semver/v3"
8+ "k8s.io/apimachinery/pkg/types"
89 "k8s.io/apimachinery/pkg/util/sets"
910
1011 rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
1112
13+ operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
1214 "github.com/operator-framework/operator-controller/internal/catalogmetadata"
1315 catalogfilter "github.com/operator-framework/operator-controller/internal/catalogmetadata/filter"
1416 catalogsort "github.com/operator-framework/operator-controller/internal/catalogmetadata/sort"
@@ -22,16 +24,21 @@ import (
2224// has own variable.
2325func MakeInstalledPackageVariables (
2426 allBundles []* catalogmetadata.Bundle ,
27+ operators []operatorsv1alpha1.Operator ,
2528 bundleDeployments []rukpakv1alpha1.BundleDeployment ,
2629) ([]* olmvariables.InstalledPackageVariable , error ) {
27- var successors successorsFunc = legacySemanticsSuccessors
28- if features .OperatorControllerFeatureGate .Enabled (features .ForceSemverUpgradeConstraints ) {
29- successors = semverSuccessors
30- }
30+ ownerIDToBundleDeployment := mapOwnerIDToBundleDeployment (bundleDeployments )
3131
32- result := make ([]* olmvariables.InstalledPackageVariable , 0 , len (bundleDeployments ))
32+ result := make ([]* olmvariables.InstalledPackageVariable , 0 , len (operators ))
3333 processed := sets.Set [string ]{}
34- for _ , bundleDeployment := range bundleDeployments {
34+ for _ , operator := range operators {
35+ bundleDeployment , ok := ownerIDToBundleDeployment [operator .UID ]
36+ if ! ok {
37+ // This can happen when an Operator is requested,
38+ // but not yet installed (e.g. no BundleDeployment created for it)
39+ continue
40+ }
41+
3542 if bundleDeployment .Spec .Template == nil {
3643 continue
3744 }
@@ -58,6 +65,7 @@ func MakeInstalledPackageVariables(
5865 })
5966 installedBundle := resultSet [0 ]
6067
68+ successors := successorsFuncForOperator (operator )
6169 upgradeEdges , err := successors (allBundles , installedBundle )
6270 if err != nil {
6371 return nil , err
@@ -76,6 +84,18 @@ func MakeInstalledPackageVariables(
7684// Must not return installed bundle as a successor
7785type successorsFunc func (allBundles []* catalogmetadata.Bundle , installedBundle * catalogmetadata.Bundle ) ([]* catalogmetadata.Bundle , error )
7886
87+ func successorsFuncForOperator (operator operatorsv1alpha1.Operator ) successorsFunc {
88+ if operator .Spec .UpgradeConstraintPolicy == operatorsv1alpha1 .UpgradeConstraintPolicyIgnore {
89+ return ignoreConstraints
90+ }
91+
92+ if features .OperatorControllerFeatureGate .Enabled (features .ForceSemverUpgradeConstraints ) {
93+ return semverSuccessors
94+ }
95+
96+ return legacySemanticsSuccessors
97+ }
98+
7999// legacySemanticsSuccessors returns successors based on legacy OLMv0 semantics
80100// which rely on Replaces, Skips and skipRange.
81101func legacySemanticsSuccessors (allBundles []* catalogmetadata.Bundle , installedBundle * catalogmetadata.Bundle ) ([]* catalogmetadata.Bundle , error ) {
@@ -119,3 +139,39 @@ func semverSuccessors(allBundles []*catalogmetadata.Bundle, installedBundle *cat
119139
120140 return upgradeEdges , nil
121141}
142+
143+ // ignoreConstraints returns all available bundles for a package
144+ // as successors of the currently installed bundle. This allows downgrades.
145+ func ignoreConstraints (allBundles []* catalogmetadata.Bundle , installedBundle * catalogmetadata.Bundle ) ([]* catalogmetadata.Bundle , error ) {
146+ currentVersion , err := installedBundle .Version ()
147+ if err != nil {
148+ return nil , err
149+ }
150+
151+ excludeSelfConstraint , err := mmsemver .NewConstraint (fmt .Sprintf ("!= %s" , currentVersion .String ()))
152+ if err != nil {
153+ return nil , err
154+ }
155+
156+ upgradeEdges := catalogfilter .Filter (allBundles , catalogfilter .And (
157+ catalogfilter .WithPackageName (installedBundle .Package ),
158+ catalogfilter .InMastermindsSemverRange (excludeSelfConstraint ),
159+ ))
160+ sort .SliceStable (upgradeEdges , func (i , j int ) bool {
161+ return catalogsort .ByVersion (upgradeEdges [i ], upgradeEdges [j ])
162+ })
163+
164+ return upgradeEdges , nil
165+ }
166+
167+ func mapOwnerIDToBundleDeployment (bundleDeployments []rukpakv1alpha1.BundleDeployment ) map [types.UID ]* rukpakv1alpha1.BundleDeployment {
168+ result := map [types.UID ]* rukpakv1alpha1.BundleDeployment {}
169+
170+ for idx := range bundleDeployments {
171+ for _ , ref := range bundleDeployments [idx ].OwnerReferences {
172+ result [ref .UID ] = & bundleDeployments [idx ]
173+ }
174+ }
175+
176+ return result
177+ }
0 commit comments