Merge pull request #46835 from wasylkowski/eventually-consistently

Automatic merge from submit-queue (batch tested with PRs 46835, 46856)

Made WaitForReplicas and EnsureDesiredReplicas use PollImmediate and improved logging.

**What this PR does / why we need it**: Most importantly, this results in better logging: timeout is logged at the level of the caller, not the helper function, helping debugging.

**Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #

**Special notes for your reviewer**:

**Release note**:

```release-note
NONE
```
This commit is contained in:
Kubernetes Submit Queue
2017-06-09 08:25:41 -07:00
committed by GitHub
2 changed files with 37 additions and 19 deletions

View File

@@ -343,27 +343,33 @@ func (rc *ResourceConsumer) GetReplicas() int {
} }
func (rc *ResourceConsumer) WaitForReplicas(desiredReplicas int) { func (rc *ResourceConsumer) WaitForReplicas(desiredReplicas int) {
timeout := 15 * time.Minute duration := 15 * time.Minute
for start := time.Now(); time.Since(start) < timeout; time.Sleep(20 * time.Second) { interval := 20 * time.Second
if desiredReplicas == rc.GetReplicas() { err := wait.PollImmediate(interval, duration, func() (bool, error) {
framework.Logf("%s: current replicas number is equal to desired replicas number: %d", rc.kind, desiredReplicas) replicas := rc.GetReplicas()
return framework.Logf("waiting for %d replicas (current: %d)", desiredReplicas, replicas)
} else { return replicas == desiredReplicas, nil // Expected number of replicas found. Exit.
framework.Logf("%s: current replicas number %d waiting to be %d", rc.kind, rc.GetReplicas(), desiredReplicas) })
} framework.ExpectNoErrorWithOffset(1, err, "timeout waiting %v for %d replicas", duration, desiredReplicas)
}
framework.Failf("timeout waiting %v for pods size to be %d", timeout, desiredReplicas)
} }
func (rc *ResourceConsumer) EnsureDesiredReplicas(desiredReplicas int, timeout time.Duration) { func (rc *ResourceConsumer) EnsureDesiredReplicas(desiredReplicas int, duration time.Duration) {
for start := time.Now(); time.Since(start) < timeout; time.Sleep(10 * time.Second) { interval := 10 * time.Second
actual := rc.GetReplicas() err := wait.PollImmediate(interval, duration, func() (bool, error) {
if desiredReplicas != actual { replicas := rc.GetReplicas()
framework.Failf("Number of replicas has changed: expected %v, got %v", desiredReplicas, actual) framework.Logf("expecting there to be %d replicas (are: %d)", desiredReplicas, replicas)
if replicas != desiredReplicas {
return false, fmt.Errorf("number of replicas changed unexpectedly")
} else {
return false, nil // Expected number of replicas found. Continue polling until timeout.
} }
framework.Logf("Number of replicas is as expected") })
// The call above always returns an error, but if it is timeout, it's OK (condition satisfied all the time).
if err == wait.ErrWaitTimeout {
framework.Logf("Number of replicas was stable over %v", duration)
return
} }
framework.Logf("Number of replicas was stable over %v", timeout) framework.ExpectNoErrorWithOffset(1, err)
} }
// Pause stops background goroutines responsible for consuming resources. // Pause stops background goroutines responsible for consuming resources.

View File

@@ -286,9 +286,15 @@ func Logf(format string, args ...interface{}) {
} }
func Failf(format string, args ...interface{}) { func Failf(format string, args ...interface{}) {
FailfWithOffset(1, format, args...)
}
// FailfWithOffset calls "Fail" and logs the error at "offset" levels above its caller
// (for example, for call chain f -> g -> FailfWithOffset(1, ...) error would be logged for "f").
func FailfWithOffset(offset int, format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...) msg := fmt.Sprintf(format, args...)
log("INFO", msg) log("INFO", msg)
Fail(nowStamp()+": "+msg, 1) Fail(nowStamp()+": "+msg, 1+offset)
} }
func Skipf(format string, args ...interface{}) { func Skipf(format string, args ...interface{}) {
@@ -1917,10 +1923,16 @@ func randomSuffix() string {
} }
func ExpectNoError(err error, explain ...interface{}) { func ExpectNoError(err error, explain ...interface{}) {
ExpectNoErrorWithOffset(1, err, explain...)
}
// ExpectNoErrorWithOffset checks if "err" is set, and if so, fails assertion while logging the error at "offset" levels above its caller
// (for example, for call chain f -> g -> ExpectNoErrorWithOffset(1, ...) error would be logged for "f").
func ExpectNoErrorWithOffset(offset int, err error, explain ...interface{}) {
if err != nil { if err != nil {
Logf("Unexpected error occurred: %v", err) Logf("Unexpected error occurred: %v", err)
} }
ExpectWithOffset(1, err).NotTo(HaveOccurred(), explain...) ExpectWithOffset(1+offset, err).NotTo(HaveOccurred(), explain...)
} }
func ExpectNoErrorWithRetries(fn func() error, maxRetries int, explain ...interface{}) { func ExpectNoErrorWithRetries(fn func() error, maxRetries int, explain ...interface{}) {