Skip to content

Commit da53bae

Browse files
tests: make ImageModeStatusReporting MCP count test more resilient on SNO
1 parent 63774ee commit da53bae

1 file changed

Lines changed: 33 additions & 54 deletions

File tree

test/extended/image_mode_status_reporting.go

Lines changed: 33 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ package extended
22

33
import (
44
"context"
5-
"errors"
65
"fmt"
76
"path/filepath"
8-
"syscall"
97
"time"
108

119
g "github.com/onsi/ginkgo/v2"
@@ -33,9 +31,7 @@ var (
3331
var _ = 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
413408
func 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).
476454
func 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

Comments
 (0)