@@ -2,10 +2,8 @@ package extended
22
33import (
44 "context"
5- "errors"
65 "fmt"
76 "path/filepath"
8- "syscall"
97 "time"
108
119 g "github.com/onsi/ginkgo/v2"
3331var _ = g .Describe ("[sig-mco][Suite:openshift/machine-config-operator/disruptive][Serial][Disruptive][OCPFeatureGate:ImageModeStatusReporting]" , g .Ordered , func () {
3432 defer g .GinkgoRecover ()
3533
36- var (
37- oc = exutil .NewCLI ("mco-image-mode-status" , exutil .KubeConfigPath ()).AsAdmin ()
38- )
34+ oc := exutil .NewCLI ("mco-image-mode-status" , exutil .KubeConfigPath ()).AsAdmin ()
3935
4036 g .JustBeforeEach (func () {
4137 extpriv .PreChecks (oc )
@@ -332,8 +328,6 @@ func validateMCNTransitions(oc *exutil.CLI, machineConfigClient *machineconfigcl
332328 logger .Infof ("Checking all conditions other than 'Updated' are False." )
333329 o .Expect (ConfirmUpdatedMCNStatus (machineConfigClient , nodeToTestName )).Should (o .BeTrue (), "Error, all conditions must be 'False' when Updated=True." )
334330 logger .Infof ("OK!\n " )
335-
336- return
337331}
338332
339333// `runMachineCountTest` runs through the general flow of validating machine count transitions in
@@ -406,66 +400,50 @@ func runMachineCountTest(machineConfigClient *machineconfigclient.Clientset, oc
406400// `validateMCPMachineCountTransitions` validates the actual machine counts reported in a MCP's
407401// status matches the expected machine counts determined by checking the node annotations of the
408402// targeted nodes. This function runs until one of the following termination conditions is met:
409- // - The expected and actual machine counts do not match within a 8 second tolerance window
403+ // - The MCP machine counts have not matched the expected counts for longer than the mismatch
404+ // deadline of 2 minutes for non-SNO clusters and 5 minutes for SNO clusters
410405// - The MCP is fully updated
411406// - The overall timeout for this function has been met
412407// - Some other error has occurred in a step of the function
413408func validateMCPMachineCountTransitions (machineConfigClient * machineconfigclient.Clientset , oc * exutil.CLI , mcpName string , startTime metav1.Time , mosc * extpriv.MachineOSConfig , layered bool ) {
414409 timeout := 15 * time .Minute
415410 interval := 10 * time .Second
416- loopCount := 3
417- // For on-cluster image mode updates, set the timeout to be longer
411+ mismatchDeadline := 2 * time .Minute
418412 if layered {
419413 logger .Infof ("Layered update, setting longer update timeout." )
420414 timeout = 45 * time .Minute
421415 interval = 30 * time .Second
422- // SNO clusters require a longer time to reconcile due to the MCC restart in
423- // reboot-required updates, so allow for more retries.
424- isSNO , isSNOErr := extpriv .IsSNOSafe (oc )
425- o .Expect (isSNOErr ).NotTo (o .HaveOccurred (), fmt .Sprintf ("Error checking if cluster is SNO: %v" , isSNOErr ))
426- if isSNO {
427- logger .Infof ("Cluster is SNO, setting higher retry count." )
428- loopCount = 10
429- }
416+ mismatchDeadline = 5 * time .Minute
430417 }
431418
419+ var firstMismatchTime time.Time
432420 o .Eventually (func () bool {
433- // Check if the MCP machine counts match what is expected from the pool's node annotation
434- // values. Note that there is some latency between when the node annotations are set and
435- // when the MCP machine counts are updates, so we'll try this a few times to make sure we
436- // don't fail just because of unlucky timing.
437- for i := 0 ; i <= loopCount ; i ++ {
438- logger .Infof ("Checking if the MCP machine counts match the expected values..." )
439- countsMatch , isConnErr := mcnAndNodeAnnotationMachineCountsMatch (machineConfigClient , oc , mcpName , mosc )
440-
441- // Handle success case
442- if countsMatch {
443- break
444- }
421+ logger .Infof ("Checking if the MCP machine counts match the expected values..." )
422+ countsMatch , isConnErr := mcnAndNodeAnnotationMachineCountsMatch (machineConfigClient , oc , mcpName , mosc )
445423
446- // Continue to next retry if there is a connection error. Connection errors are common
447- // in SNO suite runs, so we may need additional tries times to get the machine counts.
448- if isConnErr {
449- logger .Infof ("Got connection error. Waiting %v seconds then trying again." , interval )
450- return false
451- }
424+ // If we hit a connection error, continue to the next iterration
425+ if isConnErr {
426+ return false
427+ }
452428
453- // Handle case when the counts are not as expected. If we reach this point in the third
454- // itteration, we've exhausted our attempts and are likely seeing a true discrepancy
455- // between the expected and actual machine counts.
456- o .Expect (i ).NotTo (o .BeNumerically ("==" , loopCount ), "The actual MCP machine counts did not match the expected machine counts" )
457- // If we have not exhausted our attempts, wait a few seconds and check again
458- if i != (loopCount - 1 ) {
459- logger .Infof ("The MCP machine counts did match the expected values. Waiting %v seconds then trying again." , (i + 1 )* 4 )
460- time .Sleep (time .Duration ((i + 1 )* 4 ) * time .Second )
429+ // Handle the case when counts don't match, which can happen due to latency in MCP syncs
430+ if ! countsMatch {
431+ if firstMismatchTime .IsZero () {
432+ firstMismatchTime = time .Now ()
433+ }
434+ elapsed := time .Since (firstMismatchTime )
435+ if elapsed > mismatchDeadline {
436+ g .Fail (fmt .Sprintf ("MCP '%v' machine counts do not matched expected values." ,
437+ mcpName ))
461438 }
439+ logger .Infof ("Counts do not match yet. Will retry." )
440+ return false
462441 }
463442
464- // Check if the MCP is updated
465- // TODO: check if this properly handles the OCL case
443+ // Counts match — reset tracker and check if the MCP update is complete
444+ firstMismatchTime = time. Time {}
466445 return MCPIsUpdatedToNewConfig (machineConfigClient , mcpName , startTime )
467446 }, timeout , interval ).Should (o .BeTrue (), "Timed out waiting for MCP '%v' to complete update." , mcpName )
468-
469447}
470448
471449// `mcnAndNodeAnnotationMachineCountsMatch` checks whether the updated and degraded machine counts
@@ -474,17 +452,18 @@ func validateMCPMachineCountTransitions(machineConfigClient *machineconfigclient
474452// otherwise. The second boolean return is `true`if there was a connection error when trying to get
475453// a resource (this allows for resiliency in SNO clsuters).
476454func mcnAndNodeAnnotationMachineCountsMatch (machineConfigClient * machineconfigclient.Clientset , oc * exutil.CLI ,
477- mcpName string , mosc * extpriv.MachineOSConfig ) (countsMatch , isConnErr bool ) {
455+ mcpName string , mosc * extpriv.MachineOSConfig ,
456+ ) (countsMatch , isConnErr bool ) {
478457 // Get machine counts from MCP
479458 mcp , mcpErr := machineConfigClient .MachineconfigurationV1 ().MachineConfigPools ().Get (context .TODO (), mcpName , metav1.GetOptions {})
480459 // If we fail to get the MCP, it could be due to a connection error or other infrastructure
481460 // instability, so we should log a warning but not error out. This is especially important for SNO.
482461 if mcpErr != nil {
483- if errors . Is (mcpErr , syscall . ECONNREFUSED ) {
484- logger .Infof ("Error connecting to cluster when getting MCP `%v`, will retry. " , mcpName )
462+ if isTransientConnectionError (mcpErr ) {
463+ logger .Infof ("Transient error getting MCP `%v`, will retry: %v " , mcpName , mcpErr )
485464 return false , true
486465 }
487- logger .Infof ("Errored getting MCP `%v`, but not connection err. " , mcpName )
466+ logger .Infof ("Non-transient error getting MCP `%v`: %v " , mcpName , mcpErr )
488467 return false , false
489468 }
490469 actualUpdatedCount := mcp .Status .UpdatedMachineCount
@@ -495,11 +474,11 @@ func mcnAndNodeAnnotationMachineCountsMatch(machineConfigClient *machineconfigcl
495474 // If we fail to get the nodes, it could be due to a connection error or other infrastructure
496475 // instability, so we should log a warning but not error out. This is especially important for SNO.
497476 if nodesErr != nil {
498- if errors . Is (nodesErr , syscall . ECONNREFUSED ) {
499- logger .Infof ("Error getting nodes in MCP `%v`, will retry. " , mcpName )
477+ if isTransientConnectionError (nodesErr ) {
478+ logger .Infof ("Transient error getting nodes in MCP `%v`, will retry: %v " , mcpName , nodesErr )
500479 return false , true
501480 }
502- logger .Infof ("Errored getting nodes in MCP `%v`, but not connection err. " , mcpName )
481+ logger .Infof ("Non-transient error getting nodes in MCP `%v`: %v " , mcpName , nodesErr )
503482 return false , false
504483 }
505484 var expectedUpdatedCount int32
0 commit comments