Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node e2e junit test artifacts #26101

Merged
merged 1 commit into from
May 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion hack/e2e-node-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ source "${KUBE_ROOT}/hack/lib/init.sh"

focus=${FOCUS:-""}
skip=${SKIP:-""}
report=${REPORT:-"/tmp/"}

ginkgo=$(kube::util::find-binary "ginkgo")
if [[ -z "${ginkgo}" ]]; then
Expand All @@ -27,6 +28,6 @@ if [[ -z "${ginkgo}" ]]; then
fi

# Provided for backwards compatibility
"${ginkgo}" --focus=$focus --skip=$skip "${KUBE_ROOT}/test/e2e_node/" -- --alsologtostderr --v 2 --node-name $(hostname) --build-services=true --start-services=true --stop-services=true
"${ginkgo}" --focus=$focus --skip=$skip "${KUBE_ROOT}/test/e2e_node/" --report-dir=${report} -- --alsologtostderr --v 2 --node-name $(hostname) --build-services=true --start-services=true --stop-services=true

exit $?
2 changes: 2 additions & 0 deletions hack/verify-flags/known-flags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ ir-password
ir-user
jenkins-host
jenkins-jobs
junit-file-number
k8s-bin-dir
k8s-build-output
keep-gogoproto
Expand Down Expand Up @@ -366,6 +367,7 @@ resolv-conf
resource-container
resource-quota-sync-period
resource-version
results-dir
retry_time
rkt-api-endpoint
rkt-path
Expand Down
2 changes: 1 addition & 1 deletion test/e2e_node/container_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func PrePullAllImages() error {
for _, image := range ImageRegistry {
output, err := exec.Command("docker", "pull", image).CombinedOutput()
if err != nil {
glog.Warning("Could not pre-pull image %s %v output: %s", image, err, output)
glog.Warningf("Could not pre-pull image %s %v output: %s", image, err, output)
return err
}
}
Expand Down
54 changes: 17 additions & 37 deletions test/e2e_node/e2e_node_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,41 @@ import (
"fmt"
"io/ioutil"
"math/rand"
"os"
"os/exec"
"path"
"strings"
"testing"
"time"

"github.com/golang/glog"
. "github.com/onsi/ginkgo"
"github.com/onsi/ginkgo/config"
"github.com/onsi/ginkgo/types"
more_reporters "github.com/onsi/ginkgo/reporters"
. "github.com/onsi/gomega"
)

var e2es *e2eService

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.")

func TestE2eNode(t *testing.T) {
flag.Parse()

rand.Seed(time.Now().UTC().UnixNano())
RegisterFailHandler(Fail)
reporters := []Reporter{&LogReporter{}}
reporters := []Reporter{}
if *reportDir != "" {
// Create the directory if it doesn't already exists
if err := os.MkdirAll(*reportDir, 0755); err != nil {
glog.Errorf("Failed creating report directory: %v", err)
} else {
// Configure a junit reporter to write to the directory
junitFile := fmt.Sprintf("junit_%02d.xml", *junitFileNumber)
junitPath := path.Join(*reportDir, junitFile)
reporters = append(reporters, more_reporters.NewJUnitReporter(junitPath))
}
}
RunSpecsWithDefaultAndCustomReporters(t, "E2eNode Suite", reporters)
}

Expand Down Expand Up @@ -94,40 +108,6 @@ var _ = AfterSuite(func() {
glog.Infof("Tests Finished")
})

var _ Reporter = &LogReporter{}

type LogReporter struct{}

func (lr *LogReporter) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) {
b := &bytes.Buffer{}
b.WriteString("******************************************************\n")
glog.Infof(b.String())
}

func (lr *LogReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {}

func (lr *LogReporter) SpecWillRun(specSummary *types.SpecSummary) {}

func (lr *LogReporter) SpecDidComplete(specSummary *types.SpecSummary) {}

func (lr *LogReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) {}

func (lr *LogReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) {
// Only log the binary output if the suite failed.
b := &bytes.Buffer{}
if e2es != nil && !summary.SuiteSucceeded {
b.WriteString(fmt.Sprintf("Process Log For Failed Suite On %s\n", *nodeName))
b.WriteString("-------------------------------------------------------------\n")
b.WriteString(fmt.Sprintf("kubelet output:\n%s\n", e2es.kubeletCombinedOut.String()))
b.WriteString("-------------------------------------------------------------\n")
b.WriteString(fmt.Sprintf("apiserver output:\n%s\n", e2es.apiServerCombinedOut.String()))
b.WriteString("-------------------------------------------------------------\n")
b.WriteString(fmt.Sprintf("etcd output:\n%s\n", e2es.etcdCombinedOut.String()))
}
b.WriteString("******************************************************\n")
glog.Infof(b.String())
}

func maskLocksmithdOnCoreos() {
data, err := ioutil.ReadFile("/etc/os-release")
if err != nil {
Expand Down
28 changes: 26 additions & 2 deletions test/e2e_node/e2e_remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ import (
"strings"

"github.com/golang/glog"
utilerrors "k8s.io/kubernetes/pkg/util/errors"
)

var sshOptions = flag.String("ssh-options", "", "Commandline options passed to ssh.")
var sshEnv = flag.String("ssh-env", "", "Use predefined ssh options for environment. Options: gce")
var testTimeoutSeconds = flag.Int("test-timeout", 45*60, "How long (in seconds) to wait for ginkgo tests to complete.")
var resultsDir = flag.String("results-dir", "/tmp/", "Directory to scp test results to.")

var sshOptionsMap map[string]string

Expand Down Expand Up @@ -119,7 +121,7 @@ func CreateTestArchive() string {
}

// RunRemote copies the archive file to a /tmp file on host, unpacks it, and runs the e2e_node.test
func RunRemote(archive string, host string, cleanup bool) (string, error) {
func RunRemote(archive string, host string, cleanup bool, junitFileNumber int) (string, error) {
// Create the temp staging directory
glog.Infof("Staging test binaries on %s", host)
tmp := fmt.Sprintf("/tmp/gcloud-e2e-%d", rand.Int31())
Expand Down Expand Up @@ -158,17 +160,39 @@ func RunRemote(archive string, host string, cleanup bool) (string, error) {
cmd = getSshCommand(" && ",
fmt.Sprintf("cd %s", tmp),
fmt.Sprintf("tar -xzvf ./%s", archiveName),
fmt.Sprintf("timeout -k 30s %ds ./e2e_node.test --logtostderr --v 2 --build-services=false --stop-services=%t --node-name=%s", *testTimeoutSeconds, cleanup, host),
fmt.Sprintf("timeout -k 30s %ds ./e2e_node.test --logtostderr --v 2 --build-services=false --stop-services=%t --node-name=%s --report-dir=%s/results --junit-file-number=%d", *testTimeoutSeconds, cleanup, host, tmp, junitFileNumber),
)
glog.Infof("Starting tests on %s", host)
output, err := RunSshCommand("ssh", host, "--", "sh", "-c", cmd)

if err != nil {
scpErr := getTestArtifacts(host, tmp)

// Return both the testing and scp error
if scpErr != nil {
return "", utilerrors.NewAggregate([]error{err, scpErr})
}
return "", err
}

err = getTestArtifacts(host, tmp)
return output, nil
}

func getTestArtifacts(host, testDir string) error {
_, err := RunSshCommand("scp", "-r", fmt.Sprintf("%s:%s/results/", host, testDir), fmt.Sprintf("%s/%s", *resultsDir, host))
if err != nil {
return err
}

// Copy junit to the top of artifacts
_, err = RunSshCommand("scp", fmt.Sprintf("%s:%s/results/junit*", host, testDir), fmt.Sprintf("%s/", *resultsDir))
if err != nil {
return err
}
return nil
}

// getSshCommand handles proper quoting so that multiple commands are executed in the same shell over ssh
func getSshCommand(sep string, args ...string) string {
return fmt.Sprintf("'%s'", strings.Join(args, sep))
Expand Down
59 changes: 36 additions & 23 deletions test/e2e_node/e2e_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,29 @@ limitations under the License.
package e2e_node

import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path"
"strings"
"time"

"github.com/golang/glog"
)

var serverStartTimeout = flag.Duration("server-start-timeout", time.Second*120, "Time to wait for each server to become healthy.")
var reportDir = flag.String("report-dir", "", "Path to the directory where the JUnit XML reports should be saved. Default is empty, which doesn't generate these reports.")

type e2eService struct {
etcdCmd *exec.Cmd
etcdCombinedOut bytes.Buffer
etcdDataDir string
apiServerCmd *exec.Cmd
apiServerCombinedOut bytes.Buffer
kubeletCmd *exec.Cmd
kubeletCombinedOut bytes.Buffer
kubeletStaticPodDir string
nodeName string
etcdCmd *exec.Cmd
etcdDataDir string
apiServerCmd *exec.Cmd
kubeletCmd *exec.Cmd
kubeletStaticPodDir string
nodeName string
}

func newE2eService(nodeName string) *e2eService {
Expand Down Expand Up @@ -123,23 +121,23 @@ func (es *e2eService) startEtcd() (*exec.Cmd, error) {
hcc := newHealthCheckCommand(
"http://127.0.0.1:4001/v2/keys/", // Trailing slash is required,
cmd,
&es.etcdCombinedOut)
"etcd.log")
return cmd, es.startServer(hcc)
}

func (es *e2eService) startApiServer() (*exec.Cmd, error) {
cmd := exec.Command("sudo", getApiServerBin(),
"--v", "2", "--logtostderr", "--log_dir", "./",
"--etcd-servers", "http://127.0.0.1:4001",
"--insecure-bind-address", "0.0.0.0",
"--service-cluster-ip-range", "10.0.0.1/24",
"--kubelet-port", "10250",
"--allow-privileged", "true",
"--v", "8", "--logtostderr",
)
hcc := newHealthCheckCommand(
"http://127.0.0.1:8080/healthz",
cmd,
&es.apiServerCombinedOut)
"kube-apiserver.log")
return cmd, es.startServer(hcc)
}

Expand All @@ -150,7 +148,6 @@ func (es *e2eService) startKubeletServer() (*exec.Cmd, error) {
}
es.kubeletStaticPodDir = dataDir
cmd := exec.Command("sudo", getKubeletServerBin(),
"--v", "2", "--logtostderr", "--log_dir", "./",
"--api-servers", "http://127.0.0.1:8080",
"--address", "0.0.0.0",
"--port", "10250",
Expand All @@ -160,22 +157,40 @@ func (es *e2eService) startKubeletServer() (*exec.Cmd, error) {
"--serialize-image-pulls", "false",
"--config", es.kubeletStaticPodDir,
"--file-check-frequency", "10s", // Check file frequently so tests won't wait too long
"--v", "8", "--logtostderr",
)
hcc := newHealthCheckCommand(
"http://127.0.0.1:10255/healthz",
cmd,
&es.kubeletCombinedOut)
"kubelet.log")
return cmd, es.startServer(hcc)
}

func (es *e2eService) startServer(cmd *healthCheckCommand) error {
cmdErrorChan := make(chan error)
go func() {
err := cmd.Run()
defer close(cmdErrorChan)

// Create the output filename
outPath := path.Join(*reportDir, cmd.outputFilename)
outfile, err := os.Create(outPath)
if err != nil {
cmdErrorChan <- fmt.Errorf("Failed to create file %s for `%s` %v.", outPath, cmd, err)
return
}
defer outfile.Close()
defer outfile.Sync()

// Set the command to write the output file
cmd.Cmd.Stdout = outfile
cmd.Cmd.Stderr = outfile

// Run the command
err = cmd.Run()
if err != nil {
cmdErrorChan <- fmt.Errorf("%s Failed with error \"%v\". Command output:\n%s", cmd, err, cmd.OutputBuffer)
cmdErrorChan <- fmt.Errorf("%s Failed with error \"%v\". Output written to: %s", cmd, err, outPath)
return
}
close(cmdErrorChan)
}()

endTime := time.Now().Add(*serverStartTimeout)
Expand All @@ -196,16 +211,14 @@ func (es *e2eService) startServer(cmd *healthCheckCommand) error {
type healthCheckCommand struct {
*exec.Cmd
HealthCheckUrl string
OutputBuffer *bytes.Buffer
outputFilename string
}

func newHealthCheckCommand(healthCheckUrl string, cmd *exec.Cmd, combinedOutput *bytes.Buffer) *healthCheckCommand {
cmd.Stdout = combinedOutput
cmd.Stderr = combinedOutput
func newHealthCheckCommand(healthCheckUrl string, cmd *exec.Cmd, filename string) *healthCheckCommand {
return &healthCheckCommand{
HealthCheckUrl: healthCheckUrl,
Cmd: cmd,
OutputBuffer: combinedOutput,
outputFilename: filename,
}
}

Expand Down
25 changes: 25 additions & 0 deletions test/e2e_node/jenkins/copy-e2e-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nest step: Run this automatically if images don't exist.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good idea.


# Copyright 2016 The Kubernetes Authors All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Usage: copy-e2e-image.sh <image-name> <from-project-name> <to-project-name>

set -e
set -x

echo "Copying image $1 from project $2 to project $3..."
gcloud compute --project $3 disks create $1 --image=https://www.googleapis.com/compute/v1/projects/$2/global/images/$1
gcloud compute --project $3 images create $1 --source-disk=$1
gcloud compute --project $3 disks delete $1
5 changes: 4 additions & 1 deletion test/e2e_node/jenkins/e2e-node-jenkins.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ if [ "$INSTALL_GODEP" = true ] ; then
fi

go build test/e2e_node/environment/conformance.go
ARTIFACTS=${WORKSPACE}/_artifacts
mkdir -p ${ARTIFACTS}
go run test/e2e_node/runner/run_e2e.go --logtostderr --vmodule=*=2 --ssh-env="gce" \
--zone="$GCE_ZONE" --project="$GCE_PROJECT" \
--hosts="$GCE_HOSTS" --images="$GCE_IMAGES" --cleanup="$CLEANUP"
--hosts="$GCE_HOSTS" --images="$GCE_IMAGES" --cleanup="$CLEANUP" \
--results-dir="$ARTIFACTS"