Skip to content

Commit a96e7bd

Browse files
committed
cvo: set ResourceReconciliationIssues condition
When an appropriate feature flag is set, maintain a `ResourceReconciliationIssues` condition on the CV status. This condition is False when no issues were encountered (signalled by the `Failure` field on the `SyncWorkerStatus` parameter) and True otherwise.
1 parent 80004b0 commit a96e7bd

3 files changed

Lines changed: 97 additions & 2 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package cvo
2+
3+
import v1 "github.com/openshift/api/config/v1"
4+
5+
const (
6+
resourceReconciliationIssuesConditionType v1.ClusterStatusConditionType = "ResourceReconciliationIssues"
7+
noResourceReconciliationIssuesReason = "NoIssues"
8+
noResourceReconciliationIssuesMessage = "No issues found during resource reconciliation"
9+
10+
resourceReconciliationIssuesFoundReason = "IssuesFound"
11+
resourceReconciliationissuesFoundMessage = "Issues found during resource reconciliation"
12+
)

pkg/cvo/status.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ func (optr *Operator) syncStatus(ctx context.Context, original, config *configv1
198198
original = config.DeepCopy()
199199
}
200200

201-
updateClusterVersionStatus(&config.Status, status, optr.release, optr.getAvailableUpdates, validationErrs)
201+
updateClusterVersionStatus(&config.Status, status, optr.release, optr.getAvailableUpdates, optr.enabledGates, validationErrs)
202202

203203
if klog.V(6).Enabled() {
204204
klog.Infof("Apply config: %s", diff.ObjectReflectDiff(original, config))
@@ -210,7 +210,8 @@ func (optr *Operator) syncStatus(ctx context.Context, original, config *configv1
210210

211211
// updateClusterVersionStatus updates the passed cvStatus with the latest status information
212212
func updateClusterVersionStatus(cvStatus *configv1.ClusterVersionStatus, status *SyncWorkerStatus,
213-
release configv1.Release, getAvailableUpdates func() *availableUpdates, validationErrs field.ErrorList) {
213+
release configv1.Release, getAvailableUpdates func() *availableUpdates, enabledGates FeatureGates,
214+
validationErrs field.ErrorList) {
214215

215216
cvStatus.ObservedGeneration = status.Generation
216217
if len(status.VersionHash) > 0 {
@@ -379,6 +380,21 @@ func updateClusterVersionStatus(cvStatus *configv1.ClusterVersionStatus, status
379380
}
380381
}
381382

383+
if enabledGates.ResourceReconciliationIssuesCondition {
384+
rriCondition := configv1.ClusterOperatorStatusCondition{
385+
Type: resourceReconciliationIssuesConditionType,
386+
Status: configv1.ConditionFalse,
387+
Reason: noResourceReconciliationIssuesReason,
388+
Message: noResourceReconciliationIssuesMessage,
389+
}
390+
if status.Failure != nil {
391+
rriCondition.Status = configv1.ConditionTrue
392+
rriCondition.Reason = resourceReconciliationIssuesFoundReason
393+
rriCondition.Message = fmt.Sprintf("%s: %s", resourceReconciliationissuesFoundMessage, status.Failure.Error())
394+
}
395+
resourcemerge.SetOperatorStatusCondition(&cvStatus.Conditions, rriCondition)
396+
}
397+
382398
// default retrieved updates if it is not set
383399
if resourcemerge.FindOperatorStatusCondition(cvStatus.Conditions, configv1.RetrievedUpdates) == nil {
384400
resourcemerge.SetOperatorStatusCondition(&cvStatus.Conditions, configv1.ClusterOperatorStatusCondition{

pkg/cvo/status_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ import (
66
"reflect"
77
"testing"
88

9+
"github.com/google/go-cmp/cmp"
10+
"github.com/google/go-cmp/cmp/cmpopts"
11+
"github.com/openshift/cluster-version-operator/lib/resourcemerge"
912
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1013
"k8s.io/apimachinery/pkg/util/diff"
14+
"k8s.io/apimachinery/pkg/util/validation/field"
1115
"k8s.io/client-go/tools/record"
1216

1317
configv1 "github.com/openshift/api/config/v1"
@@ -190,3 +194,66 @@ func TestOperator_syncFailingStatus(t *testing.T) {
190194
})
191195
}
192196
}
197+
198+
func TestUpdateClusterVersionStatus_ResourceReconciliationIssues(t *testing.T) {
199+
ignoreLastTransitionTime := cmpopts.IgnoreFields(configv1.ClusterOperatorStatusCondition{}, "LastTransitionTime")
200+
201+
testCases := []struct {
202+
name string
203+
originalCvStatus configv1.ClusterVersionStatus
204+
syncWorkerStatus SyncWorkerStatus
205+
206+
enabled bool
207+
208+
expectedCondition *configv1.ClusterOperatorStatusCondition
209+
}{
210+
{
211+
name: "ResourceReconciliationIssues present and happy when gate is enabled and no failures happened",
212+
originalCvStatus: configv1.ClusterVersionStatus{},
213+
syncWorkerStatus: SyncWorkerStatus{},
214+
enabled: true,
215+
expectedCondition: &configv1.ClusterOperatorStatusCondition{
216+
Type: resourceReconciliationIssuesConditionType,
217+
Status: configv1.ConditionFalse,
218+
Reason: noResourceReconciliationIssuesReason,
219+
Message: noResourceReconciliationIssuesMessage,
220+
},
221+
},
222+
{
223+
name: "ResourceReconciliationIssues present and unhappy when gate is enabled and failures happened",
224+
originalCvStatus: configv1.ClusterVersionStatus{},
225+
syncWorkerStatus: SyncWorkerStatus{
226+
Failure: fmt.Errorf("Something happened"),
227+
},
228+
enabled: true,
229+
expectedCondition: &configv1.ClusterOperatorStatusCondition{
230+
Type: resourceReconciliationIssuesConditionType,
231+
Status: configv1.ConditionTrue,
232+
Reason: resourceReconciliationIssuesFoundReason,
233+
Message: fmt.Sprintf("Issues found during resource reconciliation: Something happened"),
234+
},
235+
},
236+
{
237+
name: "ResourceReconciliationIssues not present when gate is enabled and failures happened",
238+
originalCvStatus: configv1.ClusterVersionStatus{},
239+
syncWorkerStatus: SyncWorkerStatus{},
240+
enabled: false,
241+
expectedCondition: nil,
242+
},
243+
}
244+
245+
for _, tc := range testCases {
246+
tc := tc
247+
t.Run(tc.name, func(t *testing.T) {
248+
gates := FeatureGates{ResourceReconciliationIssuesCondition: tc.enabled}
249+
release := configv1.Release{}
250+
getAvailableUpdates := func() *availableUpdates { return nil }
251+
var noErrors field.ErrorList
252+
updateClusterVersionStatus(&tc.originalCvStatus, &tc.syncWorkerStatus, release, getAvailableUpdates, gates, noErrors)
253+
condition := resourcemerge.FindOperatorStatusCondition(tc.originalCvStatus.Conditions, resourceReconciliationIssuesConditionType)
254+
if diff := cmp.Diff(tc.expectedCondition, condition, ignoreLastTransitionTime); diff != "" {
255+
t.Errorf("unexpected condition\n:%s", diff)
256+
}
257+
})
258+
}
259+
}

0 commit comments

Comments
 (0)