diff --git a/docs/user/reconciliation.md b/docs/user/reconciliation.md index 3dd962200f..be2efa640d 100644 --- a/docs/user/reconciliation.md +++ b/docs/user/reconciliation.md @@ -117,7 +117,7 @@ Instead, the operators create ClusterOperator themselves. The ClusterOperator builder only monitors the in-cluster object and blocks until it is: * Available -* Either not progressing or, when the release image manifest has `status.versions` entries, listing at least the versions given in that manifest. +* The ClusterOperator contains at least the versions listed in the associated release image manifest. For example, an OpenShift API server ClusterOperator entry in the release image like: ```yaml @@ -133,8 +133,6 @@ The ClusterOperator builder only monitors the in-cluster object and blocks until ``` would block until the in-cluster ClusterOperator reported `operator` at version 4.1.0. - - The progressing check is deprecated and will be removed once all operators are reporting versions. * Not degraded (except during initialization, where we ignore the degraded status) ### CustomResourceDefinition diff --git a/pkg/cvo/internal/operatorstatus.go b/pkg/cvo/internal/operatorstatus.go index 299fcc4cca..d485216b78 100644 --- a/pkg/cvo/internal/operatorstatus.go +++ b/pkg/cvo/internal/operatorstatus.go @@ -2,9 +2,9 @@ package internal import ( "context" - "errors" "fmt" "sort" + "strings" "time" "unicode" @@ -141,85 +141,66 @@ func waitForOperatorStatusToBeDone(ctx context.Context, interval time.Duration, return false, nil } - // undone is map of operand to tuple of (expected version, actual version) - // for incomplete operands. - undone := map[string][]string{} + if len(expected.Status.Versions) == 0 { + lastErr = &payload.UpdateError{ + UpdateEffect: payload.UpdateEffectFail, + Reason: "ClusterOperatorNotAvailable", + Message: fmt.Sprintf("Cluster operator %s does not declare expected versions", expected.Name), + Name: expected.Name, + } + return false, nil + } + + // undone is a sorted slice of transition messages for incomplete operands. + undone := make([]string, 0, len(expected.Status.Versions)) for _, expOp := range expected.Status.Versions { - undone[expOp.Name] = []string{expOp.Version} + current := "" for _, actOp := range actual.Status.Versions { if actOp.Name == expOp.Name { - undone[expOp.Name] = append(undone[expOp.Name], actOp.Version) - if actOp.Version == expOp.Version { - delete(undone, expOp.Name) - } + current = actOp.Version break } } - } - if len(undone) > 0 { - var keys []string - for k := range undone { - keys = append(keys, k) - } - sort.Strings(keys) - - message := fmt.Sprintf("Cluster operator %s is still updating", actual.Name) - lastErr = &payload.UpdateError{ - Nested: errors.New(lowerFirst(message)), - UpdateEffect: payload.UpdateEffectNone, - Reason: "ClusterOperatorNotAvailable", - Message: message, - Name: actual.Name, + if current != expOp.Version { + if current == "" { + undone = append(undone, fmt.Sprintf("%s to %s", expOp.Name, expOp.Version)) + } else { + undone = append(undone, fmt.Sprintf("%s from %s to %s", expOp.Name, current, expOp.Version)) + } } - return false, nil } + sort.Strings(undone) available := false + var availableCondition *configv1.ClusterOperatorStatusCondition progressing := true - failing := true - var failingCondition *configv1.ClusterOperatorStatusCondition - degradedValue := true + degraded := true var degradedCondition *configv1.ClusterOperatorStatusCondition for i := range actual.Status.Conditions { condition := &actual.Status.Conditions[i] switch { - case condition.Type == configv1.OperatorAvailable && condition.Status == configv1.ConditionTrue: - available = true + case condition.Type == configv1.OperatorAvailable: + if condition.Status == configv1.ConditionTrue { + available = true + } + availableCondition = condition case condition.Type == configv1.OperatorProgressing && condition.Status == configv1.ConditionFalse: progressing = false case condition.Type == configv1.OperatorDegraded: if condition.Status == configv1.ConditionFalse { - degradedValue = false + degraded = false } degradedCondition = condition } } - // If degraded was an explicitly set condition, use that. If not, use the deprecated failing. - degraded := failing - if degradedCondition != nil { - degraded = degradedValue - } - - switch mode { - case resourcebuilder.InitializingMode: - // during initialization we allow degraded as long as the component goes available - if available && (!progressing || len(expected.Status.Versions) > 0) { - return true, nil - } - default: - // if we're at the correct version, and available, and not degraded, we are done - // if we're available, not degraded, and not progressing, we're also done - // TODO: remove progressing once all cluster operators report expected versions - if available && (!progressing || len(expected.Status.Versions) > 0) && !degraded { - return true, nil - } - } - - nestedMessage := fmt.Errorf("cluster operator %s conditions: available=%v, progressing=%v, degraded=%v", - actual.Name, available, progressing, degraded) + nestedMessage := fmt.Errorf("cluster operator %s: available=%v, progressing=%v, degraded=%v, undone=%s", + actual.Name, available, progressing, degraded, strings.Join(undone, ", ")) if !available { + if availableCondition != nil && len(availableCondition.Message) > 0 { + nestedMessage = fmt.Errorf("cluster operator %s is %s=%s: %s: %s", actual.Name, availableCondition.Type, availableCondition.Status, availableCondition.Reason, availableCondition.Message) + } lastErr = &payload.UpdateError{ Nested: nestedMessage, UpdateEffect: payload.UpdateEffectFail, @@ -230,13 +211,10 @@ func waitForOperatorStatusToBeDone(ctx context.Context, interval time.Duration, return false, nil } - condition := failingCondition - if degradedCondition != nil { - condition = degradedCondition - } - if condition != nil && condition.Status == configv1.ConditionTrue { - if len(condition.Message) > 0 { - nestedMessage = fmt.Errorf("cluster operator %s is reporting a message: %s", actual.Name, condition.Message) + // during initialization we allow degraded + if degraded && mode != resourcebuilder.InitializingMode { + if degradedCondition != nil && len(degradedCondition.Message) > 0 { + nestedMessage = fmt.Errorf("cluster operator %s is %s=%s: %s, %s", actual.Name, degradedCondition.Type, degradedCondition.Status, degradedCondition.Reason, degradedCondition.Message) } lastErr = &payload.UpdateError{ Nested: nestedMessage, @@ -248,14 +226,20 @@ func waitForOperatorStatusToBeDone(ctx context.Context, interval time.Duration, return false, nil } - lastErr = &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator is available and not degraded but has not finished updating to target version"), - UpdateEffect: payload.UpdateEffectNone, - Reason: "ClusterOperatorUpdating", - Message: fmt.Sprintf("Cluster operator %s is updating versions", actual.Name), - Name: actual.Name, + // during initialization we allow undone versions + if len(undone) > 0 && mode != resourcebuilder.InitializingMode { + nestedMessage = fmt.Errorf("cluster operator %s is available and not degraded but has not finished updating to target version", actual.Name) + lastErr = &payload.UpdateError{ + Nested: nestedMessage, + UpdateEffect: payload.UpdateEffectNone, + Reason: "ClusterOperatorUpdating", + Message: fmt.Sprintf("Cluster operator %s is updating versions", actual.Name), + Name: actual.Name, + } + return false, nil } - return false, nil + + return true, nil }, ctx.Done()) if err != nil { if err == wait.ErrWaitTimeout && lastErr != nil { diff --git a/pkg/cvo/internal/operatorstatus_test.go b/pkg/cvo/internal/operatorstatus_test.go index 97fa5bc98d..d30174d98e 100644 --- a/pkg/cvo/internal/operatorstatus_test.go +++ b/pkg/cvo/internal/operatorstatus_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/davecgh/go-spew/spew" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -49,9 +50,15 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { Name: "test-co", }, }, { - name: "cluster operator reporting no versions with no operands", + name: "cluster operator reporting available=true and degraded=false, but no versions", actual: &configv1.ClusterOperator{ ObjectMeta: metav1.ObjectMeta{Name: "test-co"}, + Status: configv1.ClusterOperatorStatus{ + Conditions: []configv1.ClusterOperatorStatusCondition{ + {Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, + {Type: configv1.OperatorDegraded, Status: configv1.ConditionFalse}, + }, + }, }, exp: &configv1.ClusterOperator{ ObjectMeta: metav1.ObjectMeta{Name: "test-co"}, @@ -62,16 +69,22 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co is still updating"), + Nested: fmt.Errorf("cluster operator test-co is available and not degraded but has not finished updating to target version"), UpdateEffect: payload.UpdateEffectNone, - Reason: "ClusterOperatorNotAvailable", - Message: "Cluster operator test-co is still updating", + Reason: "ClusterOperatorUpdating", + Message: "Cluster operator test-co is updating versions", Name: "test-co", }, }, { - name: "cluster operator reporting no versions", + name: "cluster operator reporting available=true, degraded=false, but no versions, while expecting an operator version", actual: &configv1.ClusterOperator{ ObjectMeta: metav1.ObjectMeta{Name: "test-co"}, + Status: configv1.ClusterOperatorStatus{ + Conditions: []configv1.ClusterOperatorStatusCondition{ + {Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, + {Type: configv1.OperatorDegraded, Status: configv1.ConditionFalse}, + }, + }, }, exp: &configv1.ClusterOperator{ ObjectMeta: metav1.ObjectMeta{Name: "test-co"}, @@ -84,17 +97,21 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co is still updating"), + Nested: fmt.Errorf("cluster operator test-co is available and not degraded but has not finished updating to target version"), UpdateEffect: payload.UpdateEffectNone, - Reason: "ClusterOperatorNotAvailable", - Message: "Cluster operator test-co is still updating", + Reason: "ClusterOperatorUpdating", + Message: "Cluster operator test-co is updating versions", Name: "test-co", }, }, { - name: "cluster operator reporting no versions for operand", + name: "cluster operator reporting available=true and degraded=false, but no versions for operand", actual: &configv1.ClusterOperator{ ObjectMeta: metav1.ObjectMeta{Name: "test-co"}, Status: configv1.ClusterOperatorStatus{ + Conditions: []configv1.ClusterOperatorStatusCondition{ + {Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, + {Type: configv1.OperatorDegraded, Status: configv1.ConditionFalse}, + }, Versions: []configv1.OperandVersion{{ Name: "operator", Version: "v0", }}, @@ -111,17 +128,21 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co is still updating"), + Nested: fmt.Errorf("cluster operator test-co is available and not degraded but has not finished updating to target version"), UpdateEffect: payload.UpdateEffectNone, - Reason: "ClusterOperatorNotAvailable", - Message: "Cluster operator test-co is still updating", + Reason: "ClusterOperatorUpdating", + Message: "Cluster operator test-co is updating versions", Name: "test-co", }, }, { - name: "cluster operator reporting old versions", + name: "cluster operator reporting available=true and degraded=false, but old versions", actual: &configv1.ClusterOperator{ ObjectMeta: metav1.ObjectMeta{Name: "test-co"}, Status: configv1.ClusterOperatorStatus{ + Conditions: []configv1.ClusterOperatorStatusCondition{ + {Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, + {Type: configv1.OperatorDegraded, Status: configv1.ConditionFalse}, + }, Versions: []configv1.OperandVersion{{ Name: "operator", Version: "v0", }, { @@ -140,21 +161,25 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co is still updating"), + Nested: fmt.Errorf("cluster operator test-co is available and not degraded but has not finished updating to target version"), UpdateEffect: payload.UpdateEffectNone, - Reason: "ClusterOperatorNotAvailable", - Message: "Cluster operator test-co is still updating", + Reason: "ClusterOperatorUpdating", + Message: "Cluster operator test-co is updating versions", Name: "test-co", }, }, { - name: "cluster operator reporting mix of desired and old versions", + name: "cluster operator reporting available=true and degraded=false, but mix of desired and old versions", actual: &configv1.ClusterOperator{ ObjectMeta: metav1.ObjectMeta{Name: "test-co"}, Status: configv1.ClusterOperatorStatus{ + Conditions: []configv1.ClusterOperatorStatusCondition{ + {Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, + {Type: configv1.OperatorDegraded, Status: configv1.ConditionFalse}, + }, Versions: []configv1.OperandVersion{{ - Name: "operator", Version: "v1", + Name: "operator", Version: "v0", }, { - Name: "operand-1", Version: "v0", + Name: "operand-1", Version: "v1", }}, }, }, @@ -169,17 +194,21 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co is still updating"), + Nested: fmt.Errorf("cluster operator test-co is available and not degraded but has not finished updating to target version"), UpdateEffect: payload.UpdateEffectNone, - Reason: "ClusterOperatorNotAvailable", - Message: "Cluster operator test-co is still updating", + Reason: "ClusterOperatorUpdating", + Message: "Cluster operator test-co is updating versions", Name: "test-co", }, }, { - name: "cluster operator reporting desired operator and old versions for 2 operands", + name: "cluster operator reporting available=true, degraded=false, and desired operator, but old versions for 2 operands", actual: &configv1.ClusterOperator{ ObjectMeta: metav1.ObjectMeta{Name: "test-co"}, Status: configv1.ClusterOperatorStatus{ + Conditions: []configv1.ClusterOperatorStatusCondition{ + {Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, + {Type: configv1.OperatorDegraded, Status: configv1.ConditionFalse}, + }, Versions: []configv1.OperandVersion{{ Name: "operator", Version: "v1", }, { @@ -202,17 +231,21 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co is still updating"), + Nested: fmt.Errorf("cluster operator test-co is available and not degraded but has not finished updating to target version"), UpdateEffect: payload.UpdateEffectNone, - Reason: "ClusterOperatorNotAvailable", - Message: "Cluster operator test-co is still updating", + Reason: "ClusterOperatorUpdating", + Message: "Cluster operator test-co is updating versions", Name: "test-co", }, }, { - name: "cluster operator reporting desired operator and mix of old and desired versions for 2 operands", + name: "cluster operator reporting available=true, degraded=false, and desired operator, but mix of old and desired versions for 2 operands", actual: &configv1.ClusterOperator{ ObjectMeta: metav1.ObjectMeta{Name: "test-co"}, Status: configv1.ClusterOperatorStatus{ + Conditions: []configv1.ClusterOperatorStatusCondition{ + {Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, + {Type: configv1.OperatorDegraded, Status: configv1.ConditionFalse}, + }, Versions: []configv1.OperandVersion{{ Name: "operator", Version: "v1", }, { @@ -235,10 +268,10 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co is still updating"), + Nested: fmt.Errorf("cluster operator test-co is available and not degraded but has not finished updating to target version"), UpdateEffect: payload.UpdateEffectNone, - Reason: "ClusterOperatorNotAvailable", - Message: "Cluster operator test-co is still updating", + Reason: "ClusterOperatorUpdating", + Message: "Cluster operator test-co is updating versions", Name: "test-co", }, }, { @@ -264,7 +297,7 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co conditions: available=false, progressing=true, degraded=true"), + Nested: fmt.Errorf("cluster operator test-co: available=false, progressing=true, degraded=true, undone="), UpdateEffect: payload.UpdateEffectFail, Reason: "ClusterOperatorNotAvailable", Message: "Cluster operator test-co is not available", @@ -294,7 +327,7 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co conditions: available=false, progressing=true, degraded=true"), + Nested: fmt.Errorf("cluster operator test-co: available=false, progressing=true, degraded=true, undone="), UpdateEffect: payload.UpdateEffectFail, Reason: "ClusterOperatorNotAvailable", Message: "Cluster operator test-co is not available", @@ -324,14 +357,14 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co conditions: available=false, progressing=true, degraded=true"), + Nested: fmt.Errorf("cluster operator test-co: available=false, progressing=true, degraded=true, undone="), UpdateEffect: payload.UpdateEffectFail, Reason: "ClusterOperatorNotAvailable", Message: "Cluster operator test-co is not available", Name: "test-co", }, }, { - name: "cluster operator reporting available=true progressing=true", + name: "cluster operator reporting available=true, degraded=false, and progressing=true", actual: &configv1.ClusterOperator{ ObjectMeta: metav1.ObjectMeta{Name: "test-co"}, Status: configv1.ClusterOperatorStatus{ @@ -340,7 +373,11 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, { Name: "operand-1", Version: "v1", }}, - Conditions: []configv1.ClusterOperatorStatusCondition{{Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, {Type: configv1.OperatorProgressing, Status: configv1.ConditionTrue}}, + Conditions: []configv1.ClusterOperatorStatusCondition{ + {Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, + {Type: configv1.OperatorDegraded, Status: configv1.ConditionFalse}, + {Type: configv1.OperatorProgressing, Status: configv1.ConditionTrue}, + }, }, }, exp: &configv1.ClusterOperator{ @@ -353,13 +390,6 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }}, }, }, - expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator is available and not degraded but has not finished updating to target version"), - UpdateEffect: payload.UpdateEffectNone, - Reason: "ClusterOperatorUpdating", - Message: "Cluster operator test-co is updating versions", - Name: "test-co", - }, }, { name: "cluster operator reporting available=true degraded=true", actual: &configv1.ClusterOperator{ @@ -370,7 +400,10 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, { Name: "operand-1", Version: "v1", }}, - Conditions: []configv1.ClusterOperatorStatusCondition{{Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, {Type: configv1.OperatorDegraded, Status: configv1.ConditionTrue, Message: "random error"}}, + Conditions: []configv1.ClusterOperatorStatusCondition{ + {Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, + {Type: configv1.OperatorDegraded, Status: configv1.ConditionTrue, Reason: "RandomReason", Message: "random error"}, + }, }, }, exp: &configv1.ClusterOperator{ @@ -384,7 +417,7 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co is reporting a message: random error"), + Nested: fmt.Errorf("cluster operator test-co is Degraded=True: RandomReason, random error"), UpdateEffect: payload.UpdateEffectFailAfterInterval, Reason: "ClusterOperatorDegraded", Message: "Cluster operator test-co is degraded", @@ -400,7 +433,11 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, { Name: "operand-1", Version: "v1", }}, - Conditions: []configv1.ClusterOperatorStatusCondition{{Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, {Type: configv1.OperatorProgressing, Status: configv1.ConditionTrue}, {Type: configv1.OperatorDegraded, Status: configv1.ConditionTrue, Message: "random error"}}, + Conditions: []configv1.ClusterOperatorStatusCondition{ + {Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue}, + {Type: configv1.OperatorProgressing, Status: configv1.ConditionTrue}, + {Type: configv1.OperatorDegraded, Status: configv1.ConditionTrue, Reason: "RandomReason", Message: "random error"}, + }, }, }, exp: &configv1.ClusterOperator{ @@ -414,7 +451,7 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator test-co is reporting a message: random error"), + Nested: fmt.Errorf("cluster operator test-co is Degraded=True: RandomReason, random error"), UpdateEffect: payload.UpdateEffectFailAfterInterval, Reason: "ClusterOperatorDegraded", Message: "Cluster operator test-co is degraded", @@ -444,10 +481,10 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { }, }, expErr: &payload.UpdateError{ - Nested: fmt.Errorf("cluster operator is available and not degraded but has not finished updating to target version"), - UpdateEffect: payload.UpdateEffectNone, - Reason: "ClusterOperatorUpdating", - Message: "Cluster operator test-co is updating versions", + Nested: fmt.Errorf("cluster operator test-co: available=true, progressing=true, degraded=true, undone="), + UpdateEffect: payload.UpdateEffectFailAfterInterval, + Reason: "ClusterOperatorDegraded", + Message: "Cluster operator test-co is degraded", Name: "test-co", }, }, { @@ -498,7 +535,8 @@ func Test_waitForOperatorStatusToBeDone(t *testing.T) { t.Fatalf("unexpected error: %v", err) } if !reflect.DeepEqual(test.expErr, err) { - t.Fatalf("Incorrect value returned -\nexpected: %#v\nreturned: %#v", test.expErr, err) + spew.Config.DisableMethods = true + t.Fatalf("Incorrect value returned -\nexpected: %s\nreturned: %s", spew.Sdump(test.expErr), spew.Sdump(err)) } }) } diff --git a/pkg/cvo/metrics.go b/pkg/cvo/metrics.go index 587addf22e..6cbcaabd5c 100644 --- a/pkg/cvo/metrics.go +++ b/pkg/cvo/metrics.go @@ -366,13 +366,17 @@ func (m *operatorMetrics) Collect(ch chan<- prometheus.Metric) { // output cluster operator version and condition info operators, _ := m.optr.coLister.List(labels.Everything()) for _, op := range operators { - // TODO: when we define how version works, report the appropriate version - var firstVersion string + var version string for _, v := range op.Status.Versions { - firstVersion = v.Version - break + if v.Name == "operator" { + version = v.Version + break + } + } + if version == "" { + klog.V(4).Infof("ClusterOperator %s is not setting the 'operator' version", op.Name) } - g := m.clusterOperatorUp.WithLabelValues(op.Name, firstVersion) + g := m.clusterOperatorUp.WithLabelValues(op.Name, version) failing := resourcemerge.IsOperatorStatusConditionTrue(op.Status.Conditions, configv1.OperatorDegraded) available := resourcemerge.IsOperatorStatusConditionTrue(op.Status.Conditions, configv1.OperatorAvailable) if available && !failing { diff --git a/pkg/cvo/metrics_test.go b/pkg/cvo/metrics_test.go index 58174345ab..d74f07fe6b 100644 --- a/pkg/cvo/metrics_test.go +++ b/pkg/cvo/metrics_test.go @@ -180,8 +180,8 @@ func Test_operatorMetrics_Collect(t *testing.T) { }, Status: configv1.ClusterOperatorStatus{ Versions: []configv1.OperandVersion{ - {Version: "10.1.5-1"}, - {Version: "10.1.5-2"}, + {Name: "operator", Version: "10.1.5-1"}, + {Name: "operand", Version: "10.1.5-2"}, }, Conditions: []configv1.ClusterOperatorStatusCondition{ {Type: configv1.OperatorAvailable, Status: configv1.ConditionTrue},