Skip to content

Commit 8cbe798

Browse files
committed
Add coverage for syncAvailableUpdates
Follow up #1367 (comment) The commit 913e324 from #1367 adds the two `upstream*` properties and use them to calculate `availableUpdates` even without fetching the updates from upstream, i.e., when `needFreshFetch==false`. It enables noticing the resolved alerts quickly. Before that change, any evaluated conditional update will stay there until `needFreshFetch==true`. This pull extends the coverage for the above behavior.
1 parent e9c1c39 commit 8cbe798

1 file changed

Lines changed: 84 additions & 0 deletions

File tree

pkg/cvo/availableupdates_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/blang/semver/v4"
1515
"github.com/google/go-cmp/cmp"
1616
"github.com/google/go-cmp/cmp/cmpopts"
17+
"github.com/openshift/api/features"
1718

1819
corev1 "k8s.io/api/core/v1"
1920
k8serrors "k8s.io/apimachinery/pkg/api/errors"
@@ -1175,3 +1176,86 @@ func Test_evaluateConditionalUpdates(t *testing.T) {
11751176
})
11761177
}
11771178
}
1179+
1180+
// The setup is to satisfy needsConditionalUpdateEval == true and
1181+
// needFreshFetch == false in the targeting function optr.syncAvailableUpdates
1182+
// so that we simulate the scenario where the operator re-evaluates conditional updates
1183+
// without fetching the updates from the upstream.
1184+
func TestOperator_syncAvailableUpdates_noticeResolvedAlertsQuickly(t *testing.T) {
1185+
now := time.Now()
1186+
optr := &Operator{
1187+
queue: workqueue.NewTypedRateLimitingQueue[any](workqueue.DefaultTypedControllerRateLimiter[any]()),
1188+
availableUpdates: &availableUpdates{
1189+
LastSyncOrConfigChange: now,
1190+
LastAttempt: now,
1191+
AcceptRisks: sets.New[string]("RiskA"),
1192+
Architecture: "amd64",
1193+
upstreamUpdates: []configv1.Release{
1194+
{
1195+
Version: "4.21.2",
1196+
},
1197+
},
1198+
// it becomes conditional because a firing alert
1199+
ConditionalUpdates: []configv1.ConditionalUpdate{
1200+
{
1201+
Release: configv1.Release{
1202+
Version: "4.21.2",
1203+
},
1204+
Conditions: []metav1.Condition{
1205+
{
1206+
Type: "Recommended",
1207+
Status: "False",
1208+
},
1209+
},
1210+
Risks: []configv1.ConditionalUpdateRisk{
1211+
{
1212+
Name: "TestAlert",
1213+
Conditions: []metav1.Condition{},
1214+
},
1215+
},
1216+
},
1217+
},
1218+
},
1219+
}
1220+
optr.minimumUpdateCheckInterval = 10 * time.Minute
1221+
cvgGates := featuregates.CvoGatesFromFeatureGate(&configv1.FeatureGate{
1222+
Status: configv1.FeatureGateStatus{
1223+
FeatureGates: []configv1.FeatureGateDetails{
1224+
{
1225+
Enabled: []configv1.FeatureGateAttributes{
1226+
{
1227+
Name: features.FeatureGateClusterUpdateAcceptRisks,
1228+
},
1229+
},
1230+
},
1231+
},
1232+
},
1233+
}, "")
1234+
if !cvgGates.AcceptRisks() {
1235+
t.Fatalf("accept risk feature is not enabled")
1236+
}
1237+
optr.enabledCVOFeatureGates = cvgGates
1238+
err := optr.syncAvailableUpdates(context.Background(), &configv1.ClusterVersion{
1239+
Spec: configv1.ClusterVersionSpec{
1240+
DesiredUpdate: &configv1.Update{
1241+
Architecture: "amd64",
1242+
},
1243+
},
1244+
})
1245+
if err != nil {
1246+
t.Fatalf("failed to sync available updates: %v", err)
1247+
}
1248+
1249+
// The conditional update is back to be an available update after evaluation.
1250+
// There was no available updates before the sync call.
1251+
expected := &availableUpdates{
1252+
Architecture: "amd64",
1253+
Updates: []configv1.Release{{
1254+
Version: "4.21.2",
1255+
}},
1256+
}
1257+
1258+
if diff := cmp.Diff(expected, optr.availableUpdates, availableUpdatesCmpOpts...); diff != "" {
1259+
t.Errorf("syncAvailableUpdates mismatch (-want +got):\n%s", diff)
1260+
}
1261+
}

0 commit comments

Comments
 (0)