Make the node e2e test run in parallel.

This commit is contained in:
Random-Liu
2016-07-18 00:52:39 -07:00
parent 17e31bacbc
commit 9d48c76361
7 changed files with 105 additions and 46 deletions

View File

@@ -20,6 +20,7 @@ package e2e_node
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
@@ -27,7 +28,6 @@ import (
"os"
"os/exec"
"path"
"strings"
"testing"
"time"
@@ -48,6 +48,27 @@ import (
var e2es *e2eService
// context is the test context shared by all parallel nodes.
// Originally we setup the test environment and initialize global variables
// in BeforeSuite, and then used the global variables in the test.
// However, after we make the test parallel, ginkgo will run all tests
// in several parallel test nodes. And for each test node, the BeforeSuite
// and AfterSuite will be run.
// We don't want to start services (kubelet, apiserver and etcd) for all
// parallel nodes, but we do want to set some globally shared variable which
// could be used in test.
// We have to use SynchronizedBeforeSuite to achieve that. The first
// function of SynchronizedBeforeSuite is only called once, and the second
// function is called in each parallel test node. The result returned by
// the first function will be the parameter of the second function.
// So we'll start all services and initialize the shared context in the first
// function, and propagate the context to all parallel test nodes in the
// second function.
// Notice no lock is needed for shared context, because context should only be
// initialized in the first function in SynchronizedBeforeSuite. After that
// it should never be modified.
var context SharedContext
var prePullImages = flag.Bool("prepull-images", true, "If true, prepull images so image pull failures do not cause test failures.")
var junitFileNumber = flag.Int("junit-file-number", 1, "Used to create junit filename - e.g. junit_01.xml.")
@@ -77,17 +98,10 @@ func TestE2eNode(t *testing.T) {
}
// Setup the kubelet on the node
var _ = BeforeSuite(func() {
var _ = SynchronizedBeforeSuite(func() []byte {
if *buildServices {
buildGo()
}
if framework.TestContext.NodeName == "" {
output, err := exec.Command("hostname").CombinedOutput()
if err != nil {
glog.Fatalf("Could not get node name from hostname %v. Output:\n%s", err, output)
}
framework.TestContext.NodeName = strings.TrimSpace(fmt.Sprintf("%s", output))
}
// Pre-pull the images tests depend on so we can fail immediately if there is an image pull issue
// This helps with debugging test flakes since it is hard to tell when a test failure is due to image pulling.
@@ -102,8 +116,9 @@ var _ = BeforeSuite(func() {
// We should mask locksmithd when provisioning the machine.
maskLocksmithdOnCoreos()
shared := &SharedContext{}
if *startServices {
e2es = newE2eService(framework.TestContext.NodeName, framework.TestContext.CgroupsPerQOS)
e2es = newE2eService(framework.TestContext.NodeName, framework.TestContext.CgroupsPerQOS, shared)
if err := e2es.start(); err != nil {
Fail(fmt.Sprintf("Unable to start node services.\n%v", err))
}
@@ -117,10 +132,28 @@ var _ = BeforeSuite(func() {
// Reference common test to make the import valid.
commontest.CurrentSuite = commontest.NodeE2E
data, err := json.Marshal(shared)
Expect(err).NotTo(HaveOccurred())
return data
}, func(data []byte) {
// Set the shared context got from the synchronized initialize function
shared := &SharedContext{}
Expect(json.Unmarshal(data, shared)).To(Succeed())
context = *shared
if framework.TestContext.NodeName == "" {
hostname, err := os.Hostname()
if err != nil {
glog.Fatalf("Could not get node name: %v", err)
}
framework.TestContext.NodeName = hostname
}
})
// Tear down the kubelet on the node
var _ = AfterSuite(func() {
var _ = SynchronizedAfterSuite(func() {}, func() {
if e2es != nil {
e2es.getLogFiles()
if *startServices && *stopServices {