Start e2e framework; print events

This commit is contained in:
Daniel Smith 2015-05-21 18:14:26 -07:00
parent 2a6cf783ec
commit 28b3224b72
4 changed files with 147 additions and 68 deletions

96
test/e2e/framework.go Normal file
View File

@ -0,0 +1,96 @@
/*
Copyright 2015 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.
*/
package e2e
import (
"fmt"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
// Framework supports common operations used by e2e tests; it will keep a client & a namespace for you.
// Eventual goal is to merge this with integration test framework.
type Framework struct {
BaseName string
Namespace *api.Namespace
Client *client.Client
}
// NewFramework makes a new framework and sets up a BeforeEach/AfterEach for
// you (you can write additional before/after each functions).
func NewFramework(baseName string) *Framework {
f := &Framework{
BaseName: baseName,
}
BeforeEach(f.beforeEach)
AfterEach(f.afterEach)
return f
}
// beforeEach gets a client and makes a namespace.
func (f *Framework) beforeEach() {
By("Creating a kubernetes client")
c, err := loadClient()
Expect(err).NotTo(HaveOccurred())
f.Client = c
By("Building a namespace api object")
namespace, err := createTestingNS(f.BaseName, f.Client)
Expect(err).NotTo(HaveOccurred())
f.Namespace = namespace
}
// afterEach deletes the namespace, after reading its events.
func (f *Framework) afterEach() {
// Print events if the test failed.
if CurrentGinkgoTestDescription().Failed {
By(fmt.Sprintf("Collecting events from namespace %q.", f.Namespace.Name))
events, err := f.Client.Events(f.Namespace.Name).List(labels.Everything(), fields.Everything())
Expect(err).NotTo(HaveOccurred())
for _, e := range events.Items {
Logf("event for %v: %v %v: %v", e.InvolvedObject.Name, e.Source, e.Reason, e.Message)
}
// Note that we don't wait for any cleanup to propagate, which means
// that if you delete a bunch of pods right before ending your test,
// you may or may not see the killing/deletion/cleanup events.
}
By(fmt.Sprintf("Destroying namespace %q for this suite.", f.Namespace.Name))
if err := f.Client.Namespaces().Delete(f.Namespace.Name); err != nil {
Failf("Couldn't delete ns %q: %s", f.Namespace.Name, err)
}
// Paranoia-- prevent reuse!
f.Namespace = nil
f.Client = nil
}
// WaitForPodRunning waits for the pod to run in the namespace.
func (f *Framework) WaitForPodRunning(podName string) error {
return waitForPodRunningInNamespace(f.Client, podName, f.Namespace.Name)
}

View File

@ -19,10 +19,10 @@ package e2e
import (
"fmt"
"net/http"
"strings"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
@ -31,20 +31,17 @@ import (
. "github.com/onsi/gomega"
)
func LaunchNetTestPodPerNode(nodes *api.NodeList, name string, c *client.Client, ns string) []string {
func LaunchNetTestPodPerNode(f *Framework, nodes *api.NodeList, name string) []string {
podNames := []string{}
totalPods := len(nodes.Items)
Expect(totalPods).NotTo(Equal(0))
for i, node := range nodes.Items {
podName := fmt.Sprintf("%s-%d", name, i)
podNames = append(podNames, podName)
Logf("Creating pod %s on node %s", podName, node.Name)
_, err := c.Pods(ns).Create(&api.Pod{
for _, node := range nodes.Items {
pod, err := f.Client.Pods(f.Namespace.Name).Create(&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: podName,
GenerateName: name + "-",
Labels: map[string]string{
"name": name,
},
@ -59,7 +56,7 @@ func LaunchNetTestPodPerNode(nodes *api.NodeList, name string, c *client.Client,
//peers >= totalPods should be asserted by the container.
//the nettest container finds peers by looking up list of svc endpoints.
fmt.Sprintf("-peers=%d", totalPods),
"-namespace=" + ns},
"-namespace=" + f.Namespace.Name},
Ports: []api.ContainerPort{{ContainerPort: 8080}},
},
},
@ -68,16 +65,16 @@ func LaunchNetTestPodPerNode(nodes *api.NodeList, name string, c *client.Client,
},
})
Expect(err).NotTo(HaveOccurred())
Logf("Created pod %s on node %s", pod.ObjectMeta.Name, node.Name)
podNames = append(podNames, pod.ObjectMeta.Name)
}
return podNames
}
var _ = Describe("Networking", func() {
f := NewFramework("nettest")
//This namespace is modified throughout the course of the test.
var namespace *api.Namespace
var svcname = "nettest"
var c *client.Client = nil
BeforeEach(func() {
//Assert basic external connectivity.
@ -91,22 +88,6 @@ var _ = Describe("Networking", func() {
if resp.StatusCode != http.StatusOK {
Failf("Unexpected error code, expected 200, got, %v (%v)", resp.StatusCode, resp)
}
By("Creating a kubernetes client")
c, err = loadClient()
Expect(err).NotTo(HaveOccurred())
By("Building a namespace api object")
namespace, err = createTestingNS("nettest", c)
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
By(fmt.Sprintf("Destroying namespace for this suite %v", namespace.Name))
if err := c.Namespaces().Delete(namespace.Name); err != nil {
Failf("Couldn't delete ns %s", err)
}
})
// First test because it has no dependencies on variables created later on.
@ -120,8 +101,8 @@ var _ = Describe("Networking", func() {
}
for _, test := range tests {
By(fmt.Sprintf("testing: %s", test.path))
data, err := c.RESTClient.Get().
Namespace(namespace.Name).
data, err := f.Client.RESTClient.Get().
Namespace(f.Namespace.Name).
AbsPath(test.path).
DoRaw()
if err != nil {
@ -139,8 +120,8 @@ var _ = Describe("Networking", func() {
return
}
By(fmt.Sprintf("Creating a service named [%s] in namespace %s", svcname, namespace.Name))
svc, err := c.Services(namespace.Name).Create(&api.Service{
By(fmt.Sprintf("Creating a service named %q in namespace %q", svcname, f.Namespace.Name))
svc, err := f.Client.Services(f.Namespace.Name).Create(&api.Service{
ObjectMeta: api.ObjectMeta{
Name: svcname,
Labels: map[string]string{
@ -166,26 +147,26 @@ var _ = Describe("Networking", func() {
defer func() {
defer GinkgoRecover()
By("Cleaning up the service")
if err = c.Services(namespace.Name).Delete(svc.Name); err != nil {
if err = f.Client.Services(f.Namespace.Name).Delete(svc.Name); err != nil {
Failf("unable to delete svc %v: %v", svc.Name, err)
}
}()
By("Creating a webserver (pending) pod on each node")
nodes, err := c.Nodes().List(labels.Everything(), fields.Everything())
nodes, err := f.Client.Nodes().List(labels.Everything(), fields.Everything())
if err != nil {
Failf("Failed to list nodes: %v", err)
}
podNames := LaunchNetTestPodPerNode(nodes, svcname, c, namespace.Name)
podNames := LaunchNetTestPodPerNode(f, nodes, svcname)
// Clean up the pods
defer func() {
defer GinkgoRecover()
By("Cleaning up the webserver pods")
for _, podName := range podNames {
if err = c.Pods(namespace.Name).Delete(podName, nil); err != nil {
if err = f.Client.Pods(f.Namespace.Name).Delete(podName, nil); err != nil {
Logf("Failed to delete pod %s: %v", podName, err)
}
}
@ -193,63 +174,67 @@ var _ = Describe("Networking", func() {
By("Waiting for the webserver pods to transition to Running state")
for _, podName := range podNames {
err = waitForPodRunningInNamespace(c, podName, namespace.Name)
err = f.WaitForPodRunning(podName)
Expect(err).NotTo(HaveOccurred())
}
By("Waiting for connectivity to be verified")
const maxAttempts = 60
passed := false
//once response OK, evaluate response body for pass/fail.
var body []byte
getDetails := func() ([]byte, error) {
return f.Client.Get().
Namespace(f.Namespace.Name).
Prefix("proxy").
Resource("services").
Name(svc.Name).
Suffix("read").
DoRaw()
}
for i := 0; i < maxAttempts && !passed; i++ {
time.Sleep(2 * time.Second)
Logf("About to make a proxy status call")
start := time.Now()
body, err = c.Get().
Namespace(namespace.Name).
getStatus := func() ([]byte, error) {
return f.Client.Get().
Namespace(f.Namespace.Name).
Prefix("proxy").
Resource("services").
Name(svc.Name).
Suffix("status").
DoRaw()
}
for i := 0; !passed; i++ { // Timeout will keep us from going forever.
time.Sleep(2 * time.Second)
Logf("About to make a proxy status call")
start := time.Now()
body, err = getStatus()
Logf("Proxy status call returned in %v", time.Since(start))
if err != nil {
Logf("Attempt %v/%v: service/pod still starting. (error: '%v')", i, maxAttempts, err)
Logf("Attempt %v: service/pod still starting. (error: '%v')", i, err)
continue
}
//Finally, we pass/fail the test based on if the container's response body, as to wether or not it was able to find peers.
switch string(body) {
case "pass":
// Finally, we pass/fail the test based on if the container's response body, as to wether or not it was able to find peers.
switch {
case string(body) == "pass":
Logf("Passed on attempt %v. Cleaning up.", i)
passed = true
case "running":
Logf("Attempt %v/%v: test still running", i, maxAttempts)
case "fail":
if body, err = c.Get().
Namespace(namespace.Name).Prefix("proxy").
Resource("services").
Name(svc.Name).Suffix("read").
DoRaw(); err != nil {
case string(body) == "running":
Logf("Attempt %v: test still running", i)
case string(body) == "fail":
if body, err = getDetails(); err != nil {
Failf("Failed on attempt %v. Cleaning up. Error reading details: %v", i, err)
} else {
Failf("Failed on attempt %v. Cleaning up. Details:\n%s", i, string(body))
}
case strings.Contains(string(body), "no endpoints available"):
Logf("Attempt %v: waiting on service/endpoints", i)
default:
Logf("Unexpected response: %q", body)
Logf("Unexpected response:\n%s", body)
}
}
if !passed {
if body, err = c.Get().
Namespace(namespace.Name).
Prefix("proxy").
Resource("services").
Name(svc.Name).
Suffix("read").
DoRaw(); err != nil {
if body, err = getDetails(); err != nil {
Failf("Timed out. Cleaning up. Error reading details: %v", err)
} else {
Failf("Timed out. Cleaning up. Details:\n%s", string(body))

View File

@ -55,8 +55,7 @@ const (
)
var _ = Describe("Reboot", func() {
var c *client.Client = nil
var c *client.Client
BeforeEach(func() {
var err error

View File

@ -27,8 +27,7 @@ import (
)
var _ = Describe("SSH", func() {
var c *client.Client = nil
var c *client.Client
BeforeEach(func() {
var err error