in integration/runner/runner.go [92:196]
func PushAndRunTests(host, testDir string) (result error) {
// Push binary.
klog.Infof("Pushing cAdvisor binary to %q...", host)
err := RunSshCommand("ssh", host, "--", "mkdir", "-p", testDir)
if err != nil {
return fmt.Errorf("failed to make remote testing directory: %v", err)
}
defer func() {
err = RunSshCommand("ssh", host, "--", "rm", "-rf", testDir)
if err != nil {
klog.Errorf("Failed to cleanup test directory: %v", err)
}
}()
err = RunSshCommand("scp", "-r", cadvisorBinary, fmt.Sprintf("%s:%s", host, testDir))
if err != nil {
return fmt.Errorf("failed to copy binary: %v", err)
}
// Start cAdvisor.
klog.Infof("Running cAdvisor on %q...", host)
portStr := strconv.Itoa(*port)
errChan := make(chan error, 1)
go func() {
err = RunSshCommand("ssh", host, "--", fmt.Sprintf("sudo GORACE='halt_on_error=1' %s --port %s --logtostderr --env_metadata_whitelist=TEST_VAR &> %s/log.txt", path.Join(testDir, cadvisorBinary), portStr, testDir))
if err != nil {
errChan <- fmt.Errorf("error running cAdvisor: %v", err)
}
}()
defer func() {
err = RunSshCommand("ssh", host, "--", "sudo", "pkill", cadvisorBinary)
if err != nil {
klog.Errorf("Failed to cleanup: %v", err)
}
}()
defer func() {
if result != nil {
// Copy logs from the host
err := RunSshCommand("scp", fmt.Sprintf("%s:%s/log.txt", host, testDir), "./")
if err != nil {
result = fmt.Errorf("error fetching logs: %v for %v", err, result)
return
}
defer os.Remove("./log.txt")
logs, err := os.ReadFile("./log.txt")
if err != nil {
result = fmt.Errorf("error reading local log file: %v for %v", err, result)
return
}
klog.Errorf("----------------------\nLogs from Host: %q\n%v\n", host, string(logs))
// Get attributes for debugging purposes.
attributes, err := getAttributes(host, portStr)
if err != nil {
klog.Errorf("Failed to read host attributes: %v", err)
}
result = fmt.Errorf("error on host %s: %v\n%+v", host, result, attributes)
}
}()
// Wait for cAdvisor to come up.
endTime := time.Now().Add(*cadvisorTimeout)
done := false
for endTime.After(time.Now()) && !done {
select {
case err := <-errChan:
// Quit early if there was an error.
return err
case <-time.After(500 * time.Millisecond):
// Stop waiting when cAdvisor is healthy..
resp, err := http.Get(fmt.Sprintf("http://%s:%s/healthz", host, portStr))
if err == nil && resp.StatusCode == http.StatusOK {
done = true
}
}
}
if !done {
return fmt.Errorf("timed out waiting for cAdvisor to come up at host %q", host)
}
// Run the tests in a retry loop.
klog.Infof("Running integration tests targeting %q...", host)
for i := 0; i <= *testRetryCount; i++ {
// Check if this is a retry
if i > 0 {
time.Sleep(time.Second * 15) // Wait 15 seconds before retrying
klog.Warningf("Retrying (%d of %d) tests on host %s due to error %v", i, *testRetryCount, host, err)
}
// Run the command
err = RunCommand("go", "test", "--timeout", testTimeout.String(), "github.com/google/cadvisor/integration/tests/...", "--host", host, "--port", portStr, "--ssh-options", *sshOptions)
if err == nil {
// On success, break out of retry loop
break
}
// Only retry on test failures caused by these known flaky failure conditions
if retryRegex == nil || !retryRegex.Match([]byte(err.Error())) {
klog.Warningf("Skipping retry for tests on host %s because error is not whitelisted", host)
break
}
}
return err
}