Merge pull request #20872 from pwittrock/node-e2e-tests

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2016-02-09 11:26:05 -08:00
commit cff7511c6a
2 changed files with 76 additions and 34 deletions

View File

@ -17,13 +17,13 @@ limitations under the License.
package gcloud package gcloud
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"math/rand" "math/rand"
"os/exec"
"net" "net"
"net/http" "net/http"
"os/exec"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
@ -55,6 +55,7 @@ type RunResult struct {
type CmdHandle struct { type CmdHandle struct {
TearDown TearDown TearDown TearDown
CombinedOutput bytes.Buffer
Output chan RunResult Output chan RunResult
LPort string LPort string
} }
@ -74,7 +75,7 @@ func (gc *gCloudClientImpl) Command(cmd string, moreargs ...string) ([]byte, err
return exec.Command("gcloud", args...).CombinedOutput() return exec.Command("gcloud", args...).CombinedOutput()
} }
func (gc *gCloudClientImpl) TunnelCommand(sudo bool, lPort string, rPort string, dir string, cmd string, moreargs ...string) ([]byte, error) { func (gc *gCloudClientImpl) TunnelCommand(sudo bool, lPort string, rPort string, dir string, cmd string, moreargs ...string) *exec.Cmd {
tunnelStr := fmt.Sprintf("-L %s:localhost:%s", lPort, rPort) tunnelStr := fmt.Sprintf("-L %s:localhost:%s", lPort, rPort)
args := []string{"compute", "ssh"} args := []string{"compute", "ssh"}
if gc.zone != "" { if gc.zone != "" {
@ -88,7 +89,7 @@ func (gc *gCloudClientImpl) TunnelCommand(sudo bool, lPort string, rPort string,
args = append(args, cmd) args = append(args, cmd)
args = append(args, moreargs...) args = append(args, moreargs...)
glog.V(2).Infof("Command gcloud %s", strings.Join(args, " ")) glog.V(2).Infof("Command gcloud %s", strings.Join(args, " "))
return exec.Command("gcloud", args...).CombinedOutput() return exec.Command("gcloud", args...)
} }
func (gc *gCloudClientImpl) CopyToHost(from string, to string) ([]byte, error) { func (gc *gCloudClientImpl) CopyToHost(from string, to string) ([]byte, error) {
@ -162,13 +163,15 @@ func (gc *gCloudClientImpl) Run(
} }
} }
// Do the setup c := gc.TunnelCommand(sudo, h.LPort, remotePort, tDir, cmd, args...)
c.Stdout = &h.CombinedOutput
c.Stderr = &h.CombinedOutput
go func() { go func() {
// Start the process // Start the process
out, err = gc.TunnelCommand(sudo, h.LPort, remotePort, tDir, cmd, args...) err = c.Run()
if err != nil { if err != nil {
glog.Errorf("command failed %v %s", err, out) glog.Errorf("command failed %v %s", err, h.CombinedOutput.Bytes())
h.Output <- RunResult{out, err, fmt.Sprintf("%s %s", cmd, strings.Join(args, " "))} h.Output <- RunResult{h.CombinedOutput.Bytes(), err, fmt.Sprintf("%s %s", cmd, strings.Join(args, " "))}
return return
} }
}() }()

View File

@ -43,6 +43,10 @@ type Result struct {
err error err error
} }
const gray = "\033[1;30m"
const blue = "\033[0;34m"
const noColour = "\033[0m"
var u = sync.WaitGroup{} var u = sync.WaitGroup{}
var zone = flag.String("zone", "", "gce zone the hosts live in") var zone = flag.String("zone", "", "gce zone the hosts live in")
var hosts = flag.String("hosts", "", "hosts to test") var hosts = flag.String("hosts", "", "hosts to test")
@ -77,18 +81,10 @@ func main() {
u.Add(1) u.Add(1)
} }
results := make(chan error) results := make(chan *TestResult)
hs := strings.Split(*hosts, ",") hs := strings.Split(*hosts, ",")
for _, h := range hs { for _, h := range hs {
go func(host string) { go func(host string) { results <- runTests(host) }(h)
out, err := runTests(host)
if err != nil {
glog.Infof("Failure Finished Host %s Test Suite %s %v", host, out, err)
} else {
glog.Infof("Success Finished Host %s Test Suite %s", host, out)
}
results <- err
}(h)
} }
// Maybe wait for user input before running tests // Maybe wait for user input before running tests
@ -96,11 +92,26 @@ func main() {
WaitForUser() WaitForUser()
} }
// Wait for all tests to complete and check for failures // Wait for all tests to complete and emit the results
errCount := 0 errCount := 0
for i := 0; i < len(hs); i++ { for i := 0; i < len(hs); i++ {
if <-results != nil { tr := <-results
host := tr.fullhost
if tr.err != nil {
errCount++ errCount++
glog.Infof("%s================================================================%s", blue, noColour)
glog.Infof("Failure Finished Host %s Test Suite %s %v", host, tr.testCombinedOutput, tr.err)
glog.V(2).Infof("----------------------------------------------------------------")
glog.V(5).Infof("Host %s Etcd Logs\n%s%s%s", host, gray, tr.etcdCombinedOutput, noColour)
glog.V(5).Infof("----------------------------------------------------------------")
glog.V(5).Infof("Host %s Apiserver Logs\n%s%s%s", host, gray, tr.apiServerCombinedOutput, noColour)
glog.V(5).Infof("----------------------------------------------------------------")
glog.V(2).Infof("Host %s Kubelet Logs\n%s%s%s", host, gray, tr.kubeletCombinedOutput, noColour)
glog.Infof("%s================================================================%s", blue, noColour)
} else {
glog.Infof("================================================================")
glog.Infof("Success Finished Host %s Test Suite %s", host, tr.testCombinedOutput)
glog.Infof("================================================================")
} }
} }
@ -123,34 +134,58 @@ func WaitForUser() {
u.Done() u.Done()
} }
func runTests(fullhost string) ([]byte, error) { type TestResult struct {
fullhost string
err error
testCombinedOutput string
etcdCombinedOutput string
apiServerCombinedOutput string
kubeletCombinedOutput string
}
func runTests(fullhost string) *TestResult {
result := &TestResult{fullhost: fullhost}
host := strings.Split(fullhost, ".")[0] host := strings.Split(fullhost, ".")[0]
c := gcloud.NewGCloudClient(host, *zone) c := gcloud.NewGCloudClient(host, *zone)
// TODO(pwittrock): Come up with something better for bootstrapping the environment. // TODO(pwittrock): Come up with something better for bootstrapping the environment.
eh, err := c.RunAndWaitTillHealthy( eh, err := c.RunAndWaitTillHealthy(
false, false, "4001", healthyTimeoutDuration, "v2/keys/", "etcd", "--data-dir", "./", "--name", "e2e-node") false, false, "4001", healthyTimeoutDuration, "v2/keys/", "etcd", "--data-dir", "./", "--name", "e2e-node")
defer func() { eh.TearDown() }() defer func() {
eh.TearDown()
result.etcdCombinedOutput = fmt.Sprintf("%s", eh.CombinedOutput.Bytes())
}()
if err != nil { if err != nil {
return nil, fmt.Errorf("Host %s failed to run command %v", host, err) result.err = fmt.Errorf("Host %s failed to run command %v", host, err)
return result
} }
apiBin := filepath.Join(kubeRoot, *kubeOutputRelPath, "kube-apiserver") apiBin := filepath.Join(kubeRoot, *kubeOutputRelPath, "kube-apiserver")
ah, err := c.RunAndWaitTillHealthy( ah, err := c.RunAndWaitTillHealthy(
true, true, "8080", healthyTimeoutDuration, "healthz", apiBin, "--service-cluster-ip-range", true, true, "8080", healthyTimeoutDuration, "healthz", apiBin, "--service-cluster-ip-range",
"10.0.0.1/24", "--insecure-bind-address", "0.0.0.0", "--etcd-servers", "http://127.0.0.1:4001", "10.0.0.1/24", "--insecure-bind-address", "0.0.0.0", "--etcd-servers", "http://127.0.0.1:4001",
"--v", "2", "--kubelet-port", "10250") "--v", "2", "--alsologtostderr", "--kubelet-port", "10250")
defer func() { ah.TearDown() }() defer func() {
ah.TearDown()
result.apiServerCombinedOutput = fmt.Sprintf("%s", ah.CombinedOutput.Bytes())
}()
if err != nil { if err != nil {
return nil, fmt.Errorf("Host %s failed to run command %v", host, err) result.err = fmt.Errorf("Host %s failed to run command %v", host, err)
return result
} }
kubeletBin := filepath.Join(kubeRoot, *kubeOutputRelPath, "kubelet") kubeletBin := filepath.Join(kubeRoot, *kubeOutputRelPath, "kubelet")
// TODO: Used --v 4 or higher and upload to gcs instead of printing to the console
// TODO: Copy /var/log/messages and upload to GCS for failed tests
kh, err := c.RunAndWaitTillHealthy( kh, err := c.RunAndWaitTillHealthy(
true, true, "10255", healthyTimeoutDuration, "healthz", kubeletBin, "--api-servers", "http://127.0.0.1:8080", true, true, "10255", healthyTimeoutDuration, "healthz", kubeletBin, "--api-servers", "http://127.0.0.1:8080",
"--logtostderr", "--address", "0.0.0.0", "--port", "10250") "--v", "2", "--alsologtostderr", "--address", "0.0.0.0", "--port", "10250")
defer func() { kh.TearDown() }() defer func() {
kh.TearDown()
result.kubeletCombinedOutput = fmt.Sprintf("%s", kh.CombinedOutput.Bytes())
}()
if err != nil { if err != nil {
return nil, fmt.Errorf("Host %s failed to run command %v", host, err) result.err = fmt.Errorf("Host %s failed to run command %v", host, err)
} }
// Run the tests // Run the tests
@ -159,10 +194,14 @@ func runTests(fullhost string) ([]byte, error) {
u.Wait() u.Wait()
glog.Infof("Running ginkgo tests against host %s", host) glog.Infof("Running ginkgo tests against host %s", host)
ginkgoTests := filepath.Join(kubeRoot, ginkgoTestRelPath) ginkgoTests := filepath.Join(kubeRoot, ginkgoTestRelPath)
return exec.Command( out, err := exec.Command(
"ginkgo", ginkgoTests, "--", "ginkgo", ginkgoTests, "--",
"--kubelet-address", fmt.Sprintf("http://127.0.0.1:%s", kh.LPort), "--kubelet-address", fmt.Sprintf("http://127.0.0.1:%s", kh.LPort),
"--api-server-address", fmt.Sprintf("http://127.0.0.1:%s", ah.LPort), "--api-server-address", fmt.Sprintf("http://127.0.0.1:%s", ah.LPort),
"--node-name", fullhost, "--node-name", fullhost,
"-logtostderr").CombinedOutput() "--v", "2", "--alsologtostderr").CombinedOutput()
result.err = err
result.testCombinedOutput = fmt.Sprintf("%s", out)
return result
} }