@@ -26,7 +26,7 @@ import (
2626
2727// exceptionCallback consumes a suspicious condition and returns an
2828// exception string if does not think the condition should be fatal.
29- type exceptionCallback func (operator string , condition * configv1.ClusterOperatorStatusCondition , eventInterval monitorapi.Interval , clientConfig * rest. Config ) string
29+ type exceptionCallback func (operator string , condition * configv1.ClusterOperatorStatusCondition , eventInterval monitorapi.Interval ) string
3030
3131type upgradeWindowHolder struct {
3232 startInterval * monitorapi.Interval
@@ -46,14 +46,8 @@ func checkAuthenticationAvailableExceptions(condition *configv1.ClusterOperatorS
4646 return false
4747}
4848
49- func testStableSystemOperatorStateTransitions (events monitorapi.Intervals , clientConfig * rest.Config ) []* junitapi.JUnitTestCase {
50- topology , err := getControlPlaneTopology (clientConfig )
51- if err != nil {
52- logrus .Warnf ("Error checking for ControlPlaneTopology configuration (unable to make topology exceptions): %v" , err )
53- }
54- isSingleNode := topology == configv1 .SingleReplicaTopologyMode
55-
56- except := func (operator string , condition * configv1.ClusterOperatorStatusCondition , _ monitorapi.Interval , clientConfig * rest.Config ) string {
49+ func testStableSystemOperatorStateTransitions (events monitorapi.Intervals , topology configv1.TopologyMode ) []* junitapi.JUnitTestCase {
50+ except := func (operator string , condition * configv1.ClusterOperatorStatusCondition , _ monitorapi.Interval ) string {
5751 if condition .Status == configv1 .ConditionTrue {
5852 if condition .Type == configv1 .OperatorAvailable {
5953 return fmt .Sprintf ("%s=%s is the happy case" , condition .Type , condition .Status )
@@ -64,30 +58,6 @@ func testStableSystemOperatorStateTransitions(events monitorapi.Intervals, clien
6458 }
6559 }
6660
67- if isSingleNode {
68- switch operator {
69- case "dns" :
70- if condition .Type == configv1 .OperatorAvailable && condition .Status == configv1 .ConditionFalse &&
71- strings .Contains (condition .Message , `DNS "default" is unavailable.` ) {
72- return "dns operator is allowed to have Available=False due to serial taint tests on single node"
73- }
74- if condition .Type == configv1 .OperatorDegraded && condition .Status == configv1 .ConditionTrue &&
75- strings .Contains (condition .Message , `DNS default is degraded` ) {
76- return "dns operator is allowed to have Degraded=True due to serial taint tests on single node"
77- }
78- case "openshift-apiserver" :
79- if condition .Type == configv1 .OperatorAvailable && condition .Status == configv1 .ConditionFalse &&
80- strings .Contains (condition .Message , `connect: connection refused` ) {
81- return "openshift apiserver operator is allowed to have Available=False due kube-apiserver force rollout test on single node"
82- }
83- case "csi-snapshot-controller" :
84- if condition .Type == configv1 .OperatorAvailable && condition .Status == configv1 .ConditionFalse &&
85- strings .Contains (condition .Message , `Waiting for Deployment` ) {
86- return "csi snapshot controller is allowed to have Available=False due to CSI webhook test on single node"
87- }
88- }
89- }
90-
9161 // For the non-upgrade case, if any operator has Available=False, fail the test.
9262 if condition .Type == configv1 .OperatorAvailable && condition .Status == configv1 .ConditionFalse {
9363 if operator == "authentication" {
@@ -141,7 +111,7 @@ func testStableSystemOperatorStateTransitions(events monitorapi.Intervals, clien
141111 return "We are not worried about other operator condition blips for stable-system tests yet."
142112 }
143113
144- return testOperatorStateTransitions (events , []configv1.ClusterStatusConditionType {configv1 .OperatorAvailable , configv1 .OperatorDegraded }, except , clientConfig , false )
114+ return testOperatorStateTransitions (events , []configv1.ClusterStatusConditionType {configv1 .OperatorAvailable , configv1 .OperatorDegraded }, except , false , topology )
145115}
146116
147117func getControlPlaneTopology (clientConfig * rest.Config ) (configv1.TopologyMode , error ) {
@@ -260,26 +230,17 @@ func hasUpgradeFailedEvent(eventList monitorapi.Intervals) bool {
260230 return false
261231}
262232
263- func testUpgradeOperatorStateTransitions (events monitorapi.Intervals , clientConfig * rest.Config ) []* junitapi.JUnitTestCase {
233+ func testUpgradeOperatorStateTransitions (events monitorapi.Intervals , clientConfig * rest.Config , topology configv1. TopologyMode ) []* junitapi.JUnitTestCase {
264234 upgradeWindows := getUpgradeWindows (events )
265- topology , err := getControlPlaneTopology (clientConfig )
266- if err != nil {
267- logrus .Warnf ("Error checking for ControlPlaneTopology configuration on upgrade (unable to make topology exceptions): %v" , err )
268- }
269235
270- isSingleNode := topology == configv1 .SingleReplicaTopologyMode
271236 isTwoNode := topology == configv1 .HighlyAvailableArbiterMode || topology == configv1 .DualReplicaTopologyMode
272237 upgradeFailed := hasUpgradeFailedEvent (events )
273238
274- except := func (operator string , condition * configv1.ClusterOperatorStatusCondition , eventInterval monitorapi.Interval , clientConfig * rest. Config ) string {
239+ except := func (operator string , condition * configv1.ClusterOperatorStatusCondition , eventInterval monitorapi.Interval ) string {
275240 // When an upgrade was recorded as failed, we will not care about the operator state transitions
276241 if upgradeFailed {
277242 return "upgrade failed, not recording unexpected operator transitions as failure"
278243 }
279- // SingleNode is expected to go Available=False and Degraded=True for most / all operators during upgrade
280- if isSingleNode {
281- return "single node is allowed to be unavailable/degraded during upgrades"
282- }
283244
284245 if condition .Status == configv1 .ConditionTrue {
285246 if condition .Type == configv1 .OperatorAvailable {
@@ -430,9 +391,6 @@ func testUpgradeOperatorStateTransitions(events monitorapi.Intervals, clientConf
430391 }
431392 case "kube-apiserver" :
432393 if condition .Type == configv1 .OperatorDegraded && condition .Status == configv1 .ConditionTrue {
433- if isSingleNode && condition .Reason == "NodeInstaller_InstallerPodFailed" {
434- return "https://issues.redhat.com/browse/OCPBUGS-38678"
435- }
436394 return "https://issues.redhat.com/browse/OCPBUGS-38661"
437395 }
438396 case "kube-controller-manager" :
@@ -455,7 +413,7 @@ func testUpgradeOperatorStateTransitions(events monitorapi.Intervals, clientConf
455413 return ""
456414 }
457415
458- return testOperatorStateTransitions (events , []configv1.ClusterStatusConditionType {configv1 .OperatorAvailable , configv1 .OperatorDegraded }, except , clientConfig , true )
416+ return testOperatorStateTransitions (events , []configv1.ClusterStatusConditionType {configv1 .OperatorAvailable , configv1 .OperatorDegraded }, except , true , topology )
459417}
460418
461419func isVSphere (config * rest.Config ) (bool , error ) {
@@ -506,7 +464,7 @@ func checkReplicas(namespace string, operator string, clientConfig *rest.Config)
506464 return 0 , fmt .Errorf ("Error fetching replicas" )
507465}
508466
509- func testOperatorStateTransitions (events monitorapi.Intervals , conditionTypes []configv1.ClusterStatusConditionType , except exceptionCallback , clientConfig * rest. Config , upgrade bool ) []* junitapi.JUnitTestCase {
467+ func testOperatorStateTransitions (events monitorapi.Intervals , conditionTypes []configv1.ClusterStatusConditionType , except exceptionCallback , upgrade bool , topology configv1. TopologyMode ) []* junitapi.JUnitTestCase {
510468 ret := []* junitapi.JUnitTestCase {}
511469
512470 var start , stop time.Time
@@ -527,14 +485,22 @@ func testOperatorStateTransitions(events monitorapi.Intervals, conditionTypes []
527485 bzComponent := platformidentification .GetBugzillaComponentForOperator (operatorName )
528486 testName := fmt .Sprintf ("[bz-%v] clusteroperator/%v should not change condition/%v" , bzComponent , operatorName , conditionType )
529487 operatorEvents := eventsByOperator [operatorName ]
488+ if topology == configv1 .SingleReplicaTopologyMode {
489+ ret = append (ret , & junitapi.JUnitTestCase {
490+ Name : testName ,
491+ SkipMessage : & junitapi.SkipMessage {
492+ Message : "Test skipped on a single-node cluster" ,
493+ },
494+ })
495+ continue
496+ }
530497 if len (operatorEvents ) == 0 {
531498 ret = append (ret , & junitapi.JUnitTestCase {
532499 Name : testName ,
533500 Duration : duration ,
534501 })
535502 continue
536503 }
537-
538504 excepted := []string {}
539505 fatal := []string {}
540506
@@ -570,7 +536,7 @@ func testOperatorStateTransitions(events monitorapi.Intervals, conditionTypes []
570536 if len (concurrentE2E ) > 0 {
571537 failure = fmt .Sprintf ("%s\n %d tests failed during this blip (%v to %v): %v" , failure , len (concurrentE2E ), eventInterval .From , eventInterval .To , strings .Join (concurrentE2E , "\n " ))
572538 }
573- exception := except (operatorName , condition , eventInterval , clientConfig )
539+ exception := except (operatorName , condition , eventInterval )
574540 if exception == "" {
575541 fatal = append (fatal , failure )
576542 } else {
@@ -619,22 +585,12 @@ func testOperatorStateTransitions(events monitorapi.Intervals, conditionTypes []
619585 return ret
620586}
621587
622- func testUpgradeOperatorProgressingStateTransitions (events monitorapi.Intervals , isPatchLevelUpgrade bool , clientConfig * rest. Config ) []* junitapi.JUnitTestCase {
588+ func testUpgradeOperatorProgressingStateTransitions (events monitorapi.Intervals , isPatchLevelUpgrade bool , topology configv1. TopologyMode ) []* junitapi.JUnitTestCase {
623589 var ret []* junitapi.JUnitTestCase
624590 upgradeWindows := getUpgradeWindows (events )
625591 multiUpgrades := platformidentification .UpgradeNumberDuringCollection (events , time.Time {}, time.Time {}) > 1
626592
627- isTwoNode := false
628- isSingleNode := false
629- if clientConfig != nil {
630- topology , err := getControlPlaneTopology (clientConfig )
631- if err != nil {
632- logrus .Warnf ("Error checking for ControlPlaneTopology configuration for MCO co-progressing monitor (unable to apply topology exceptions): %v" , err )
633- } else {
634- isTwoNode = topology == configv1 .HighlyAvailableArbiterMode || topology == configv1 .DualReplicaTopologyMode
635- isSingleNode = topology == configv1 .SingleReplicaTopologyMode
636- }
637- }
593+ isTwoNode := topology == configv1 .HighlyAvailableArbiterMode || topology == configv1 .DualReplicaTopologyMode
638594
639595 var machineConfigProgressingStart time.Time
640596 var eventsInUpgradeWindows monitorapi.Intervals
@@ -715,6 +671,10 @@ func testUpgradeOperatorProgressingStateTransitions(events monitorapi.Intervals,
715671 mcTestCase .SkipMessage = & junitapi.SkipMessage {
716672 Message : "Test skipped in a patch-level upgrade test" ,
717673 }
674+ } else if topology == configv1 .SingleReplicaTopologyMode {
675+ mcTestCase .SkipMessage = & junitapi.SkipMessage {
676+ Message : "Test skipped on a single-node cluster" ,
677+ }
718678 } else if t , ok := coProgressingStart [operatorName ]; ! ok || t .IsZero () {
719679 output := fmt .Sprintf ("clusteroperator/%s was never Progressing=True during the upgrade window from %s to %s" , operatorName , start .Format (time .RFC3339 ), stop .Format (time .RFC3339 ))
720680 exception = except (operatorName , "" )
@@ -792,22 +752,6 @@ func testUpgradeOperatorProgressingStateTransitions(events monitorapi.Intervals,
792752 if reason == "_ManagedDeploymentsAvailable" {
793753 return "https://issues.redhat.com/browse/OCPBUGS-62633"
794754 }
795- case "olm" :
796- // CatalogdDeploymentCatalogdControllerManager_Deploying
797- // OperatorcontrollerDeploymentOperatorControllerControllerManager_Deploying
798- // On HA, cluster-olm-operator PR #202 (2 replicas + PDB) prevents this.
799- // On SNO there is only one replica and the node reboot restarts all pods simultaneously.
800- if strings .HasSuffix (reason , "ControllerManager_Deploying" ) && isSingleNode {
801- return "https://issues.redhat.com/browse/OCPBUGS-62635"
802- }
803- case "operator-lifecycle-manager-packageserver" :
804- // On HA, isAPIServiceBackendDisrupted() in operator-framework-olm detects terminating
805- // pods and returns RetryableError to prevent the CSV phase from changing to Failed.
806- // On SNO the OS-level node reboot kills all pods simultaneously so no terminating pod
807- // is ever observed; the detection does not fire and Progressing=True is still set.
808- if reason == "" && isSingleNode {
809- return "https://issues.redhat.com/browse/OCPBUGS-63672"
810- }
811755 case "openshift-apiserver" :
812756 if isTwoNode && reason == "OperatorConfig_NewGeneration" {
813757 return "openshift-apiserver operator may reconcile openshiftapiserveroperatorconfigs (OperatorConfig_NewGeneration) during DualReplica upgrades while machine-config is progressing"
@@ -821,6 +765,15 @@ func testUpgradeOperatorProgressingStateTransitions(events monitorapi.Intervals,
821765 bzComponent := platformidentification .GetBugzillaComponentForOperator (operatorName )
822766 testName := fmt .Sprintf ("[bz-%v] clusteroperator/%v should stay Progressing=False while MCO is Progressing=True" , bzComponent , operatorName )
823767 operatorEvents := eventsByOperator [operatorName ]
768+ if topology == configv1 .SingleReplicaTopologyMode {
769+ ret = append (ret , & junitapi.JUnitTestCase {
770+ Name : testName ,
771+ SkipMessage : & junitapi.SkipMessage {
772+ Message : "Test skipped on a single-node cluster" ,
773+ },
774+ })
775+ continue
776+ }
824777 if len (operatorEvents ) == 0 {
825778 ret = append (ret , & junitapi.JUnitTestCase {
826779 Name : testName ,
0 commit comments