Skip to content

Commit 9780e9a

Browse files
committed
fix(openshift): ignore invalid max properties
Fail open when olm.maxOpenShiftVersion properties have invalid values. This means that all invalid values are logged but are ultimately ignored when determining cluster upgradeability. See https://bugzilla.redhat.com/show_bug.cgi?id=1986753 for motivation. Signed-off-by: Nick Hale <[email protected]>
1 parent 9950875 commit 9780e9a

File tree

4 files changed

+68
-17
lines changed

4 files changed

+68
-17
lines changed

pkg/controller/operators/openshift/clusteroperator_controller.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,13 @@ func (r *ClusterOperatorReconciler) setUpgradeable(ctx context.Context, co *Clus
229229
} else {
230230
incompatible, err := incompatibleOperators(ctx, r.Client)
231231
if err != nil {
232-
return err
232+
if trans := transientErrors(err); trans != nil {
233+
// Only return the error if it's transient and can be resolved by retrying
234+
return trans
235+
}
236+
237+
// TODO(njhale): less intense logging?
238+
r.Log.Error(err, "errors encountered while finding incompatible operators")
233239
}
234240

235241
if len(incompatible) > 0 {

pkg/controller/operators/openshift/clusteroperator_controller_test.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,15 @@ var _ = Describe("ClusterOperator controller", func() {
160160
incompatible.SetName("xenomorph")
161161
incompatible.SetNamespace(ns.GetName())
162162

163-
withMax := func(version string) map[string]string {
164-
maxProperty := &api.Property{
165-
Type: MaxOpenShiftVersionProperty,
166-
Value: version,
163+
withMax := func(versions ...string) map[string]string {
164+
var properties []*api.Property
165+
for _, v := range versions {
166+
properties = append(properties, &api.Property{
167+
Type: MaxOpenShiftVersionProperty,
168+
Value: v,
169+
})
167170
}
168-
value, err := projection.PropertiesAnnotationFromPropertyList([]*api.Property{maxProperty})
171+
value, err := projection.PropertiesAnnotationFromPropertyList(properties)
169172
Expect(err).ToNot(HaveOccurred())
170173

171174
return map[string]string{
@@ -245,5 +248,29 @@ var _ = Describe("ClusterOperator controller", func() {
245248
}.String(),
246249
LastTransitionTime: fixedNow(),
247250
}))
251+
252+
By("ignoring invalid versions")
253+
incompatible.SetAnnotations(withMax(fmt.Sprintf(`"%s"`, clusterVersion), `" "`, `"garbage"`))
254+
255+
Eventually(func() error {
256+
return k8sClient.Update(ctx, incompatible)
257+
}).Should(Succeed())
258+
259+
Eventually(func() ([]configv1.ClusterOperatorStatusCondition, error) {
260+
err := k8sClient.Get(ctx, clusterOperatorName, co)
261+
return co.Status.Conditions, err
262+
}, timeout).Should(ContainElement(configv1.ClusterOperatorStatusCondition{
263+
Type: configv1.OperatorUpgradeable,
264+
Status: configv1.ConditionFalse,
265+
Reason: IncompatibleOperatorsInstalled,
266+
Message: skews{
267+
{
268+
namespace: ns.GetName(),
269+
name: incompatible.GetName(),
270+
maxOpenShiftVersion: clusterVersion,
271+
},
272+
}.String(),
273+
LastTransitionTime: fixedNow(),
274+
}))
248275
})
249276
})

pkg/controller/operators/openshift/helpers.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package openshift
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"strings"
78

@@ -98,6 +99,16 @@ func (s skew) String() string {
9899
return fmt.Sprintf("Operator %s in namespace %s is not compatible with OpenShift versions greater than %s", s.name, s.namespace, s.maxOpenShiftVersion)
99100
}
100101

102+
type transientError struct {
103+
error
104+
}
105+
106+
func transientErrors(err error) error {
107+
return utilerrors.FilterOut(err, func(e error) bool {
108+
return !errors.As(e, new(transientError))
109+
})
110+
}
111+
101112
func incompatibleOperators(ctx context.Context, cli client.Client) (skews, error) {
102113
next, err := desiredRelease(ctx, cli)
103114
if err != nil {
@@ -111,7 +122,7 @@ func incompatibleOperators(ctx context.Context, cli client.Client) (skews, error
111122

112123
csvList := &operatorsv1alpha1.ClusterServiceVersionList{}
113124
if err := cli.List(ctx, csvList); err != nil {
114-
return nil, err
125+
return nil, &transientError{err}
115126
}
116127

117128
var (
@@ -126,7 +137,6 @@ func incompatibleOperators(ctx context.Context, cli client.Client) (skews, error
126137
max, err := maxOpenShiftVersion(&csv)
127138
if err != nil {
128139
errs = append(errs, err)
129-
continue
130140
}
131141
if max == nil || max.GTE(*next) {
132142
continue
@@ -139,13 +149,13 @@ func incompatibleOperators(ctx context.Context, cli client.Client) (skews, error
139149
})
140150
}
141151

142-
return s, utilerrors.NewAggregate(errs)
152+
return s, utilerrors.Flatten(utilerrors.NewAggregate(errs)) // Flatten to allow for the use of a .As in a utilerrors.Matcher function
143153
}
144154

145155
func desiredRelease(ctx context.Context, cli client.Client) (*semver.Version, error) {
146156
cv := configv1.ClusterVersion{}
147157
if err := cli.Get(ctx, client.ObjectKey{Name: "version"}, &cv); err != nil { // "version" is the name of OpenShift's ClusterVersion singleton
148-
return nil, err
158+
return nil, &transientError{err}
149159
}
150160

151161
v := cv.Status.Desired.Version
@@ -224,11 +234,7 @@ func maxOpenShiftVersion(csv *operatorsv1alpha1.ClusterServiceVersion) (*semver.
224234
}
225235
}
226236

227-
if len(errs) > 0 {
228-
return nil, utilerrors.NewAggregate(errs)
229-
}
230-
231-
return max, nil
237+
return max, utilerrors.NewAggregate(errs)
232238
}
233239

234240
func notCopiedSelector() (labels.Selector, error) {

pkg/controller/operators/openshift/helpers_test.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ func TestMaxOpenShiftVersion(t *testing.T) {
532532
},
533533
expect: expect{
534534
err: true,
535-
max: nil,
535+
max: mustParse("1.0.0"),
536536
},
537537
},
538538
{
@@ -585,7 +585,19 @@ func TestMaxOpenShiftVersion(t *testing.T) {
585585
},
586586
expect: expect{
587587
err: true,
588-
max: nil,
588+
max: mustParse("1.0.0+1"), // test assumes the order is stable
589+
},
590+
},
591+
{
592+
description: "Ambiguous/NonMax",
593+
in: []string{
594+
`"1.0.0"`,
595+
`"1.0.0+1"`,
596+
`"2.0.0"`,
597+
},
598+
expect: expect{
599+
err: false,
600+
max: mustParse("2.0.0"),
589601
},
590602
},
591603
{

0 commit comments

Comments
 (0)