diff --git a/test/e2e/framework/ssh/ssh.go b/test/e2e/framework/ssh/ssh.go index c71ab599df3..86ccdcbefff 100644 --- a/test/e2e/framework/ssh/ssh.go +++ b/test/e2e/framework/ssh/ssh.go @@ -24,6 +24,7 @@ import ( "net" "os" "path/filepath" + "sync" "time" "github.com/onsi/gomega" @@ -133,13 +134,41 @@ func NodeSSHHosts(c clientset.Interface) ([]string, error) { len(hosts), len(nodelist.Items), nodelist) } - sshHosts := make([]string, 0, len(hosts)) - for _, h := range hosts { - sshHosts = append(sshHosts, net.JoinHostPort(h, SSHPort)) + lenHosts := len(hosts) + wg := &sync.WaitGroup{} + wg.Add(lenHosts) + sshHosts := make([]string, 0, lenHosts) + var sshHostsLock sync.Mutex + + for _, host := range hosts { + go func(host string) { + defer wg.Done() + if canConnect(host) { + e2elog.Logf("Assuming SSH on host %s", host) + sshHostsLock.Lock() + sshHosts = append(sshHosts, net.JoinHostPort(host, SSHPort)) + sshHostsLock.Unlock() + } else { + e2elog.Logf("Skipping host %s because it does not run anything on port %s", host, SSHPort) + } + }(host) } + wg.Wait() + return sshHosts, nil } +// canConnect returns true if a network connection is possible to the SSHPort. +func canConnect(host string) bool { + hostPort := net.JoinHostPort(host, SSHPort) + conn, err := net.DialTimeout("tcp", hostPort, 3*time.Second) + if err != nil { + return false + } + conn.Close() + return true +} + // Result holds the execution result of SSH command type Result struct { User string diff --git a/test/e2e/node/crictl.go b/test/e2e/node/crictl.go index 7d35012c4da..86ba1bdd6b4 100644 --- a/test/e2e/node/crictl.go +++ b/test/e2e/node/crictl.go @@ -44,6 +44,7 @@ var _ = SIGDescribe("crictl", func() { if err != nil { framework.Failf("Error getting node hostnames: %v", err) } + e2eskipper.SkipUnlessAtLeast(len(hosts), 1, "Skipping test because found no SSH'able node") testCases := []struct { cmd string @@ -53,22 +54,22 @@ var _ = SIGDescribe("crictl", func() { } for _, testCase := range testCases { - // Choose an arbitrary node to test. - host := hosts[0] - ginkgo.By(fmt.Sprintf("SSH'ing to node %q to run %q", host, testCase.cmd)) + for _, host := range hosts { + ginkgo.By(fmt.Sprintf("SSH'ing to node %q to run %q", host, testCase.cmd)) - result, err := e2essh.SSH(testCase.cmd, host, framework.TestContext.Provider) - stdout, stderr := strings.TrimSpace(result.Stdout), strings.TrimSpace(result.Stderr) - if err != nil { - framework.Failf("Ran %q on %q, got error %v", testCase.cmd, host, err) - } - // Log the stdout/stderr output. - // TODO: Verify the output. - if len(stdout) > 0 { - framework.Logf("Got stdout from %q:\n %s\n", host, strings.TrimSpace(stdout)) - } - if len(stderr) > 0 { - framework.Logf("Got stderr from %q:\n %s\n", host, strings.TrimSpace(stderr)) + result, err := e2essh.SSH(testCase.cmd, host, framework.TestContext.Provider) + stdout, stderr := strings.TrimSpace(result.Stdout), strings.TrimSpace(result.Stderr) + if err != nil { + framework.Failf("Ran %q on %q, got error %v", testCase.cmd, host, err) + } + // Log the stdout/stderr output. + // TODO: Verify the output. + if len(stdout) > 0 { + framework.Logf("Got stdout from %q:\n %s\n", host, strings.TrimSpace(stdout)) + } + if len(stderr) > 0 { + framework.Logf("Got stderr from %q:\n %s\n", host, strings.TrimSpace(stderr)) + } } } })