Merge pull request #26470 from timstclair/node-e2e

Automatic merge from submit-queue

Refactor common pod patterns to e2e framework.

Priveledged pods could benifit from this as well, but I'll wait for https://github.com/kubernetes/kubernetes/pull/26228 to go in.

Prerequisite for https://github.com/kubernetes/kubernetes/issues/26215
This commit is contained in:
k8s-merge-robot
2016-06-29 15:35:02 -07:00
committed by GitHub
12 changed files with 166 additions and 119 deletions

View File

@@ -121,13 +121,8 @@ var _ = framework.KubeDescribe("ConfigMap", func() {
},
}
assignPodToNode(pod)
By("Creating the pod")
_, err = f.Client.Pods(f.Namespace.Name).Create(pod)
Expect(err).NotTo(HaveOccurred())
framework.ExpectNoError(framework.WaitForPodRunningInNamespace(f.Client, pod.Name, f.Namespace.Name))
f.CreatePod(pod)
pollLogs := func() (string, error) {
return framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, containerName)
@@ -184,7 +179,7 @@ var _ = framework.KubeDescribe("ConfigMap", func() {
},
}
assignPodToNode(pod)
f.MungePodSpec(pod)
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{
"CONFIG_DATA_1=value-1",
@@ -265,7 +260,7 @@ func doConfigMapE2EWithoutMappings(f *framework.Framework, uid, fsGroup int64) {
pod.Spec.SecurityContext.FSGroup = &fsGroup
}
assignPodToNode(pod)
f.MungePodSpec(pod)
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{
"content of file \"/etc/configmap-volume/data-1\": value-1",
@@ -338,7 +333,7 @@ func doConfigMapE2EWithMappings(f *framework.Framework, uid, fsGroup int64) {
pod.Spec.SecurityContext.FSGroup = &fsGroup
}
assignPodToNode(pod)
f.MungePodSpec(pod)
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{
"content of file \"/etc/configmap-volume/path/to/data-2\": value-2",

View File

@@ -21,24 +21,23 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/test/e2e/framework"
)
// One pod one container
// TODO: This should be migrated to the e2e framework.
type ConformanceContainer struct {
Framework *framework.Framework
Container api.Container
Client *client.Client
RestartPolicy api.RestartPolicy
Volumes []api.Volume
ImagePullSecrets []string
NodeName string
Namespace string
podName string
}
func (cc *ConformanceContainer) Create() error {
func (cc *ConformanceContainer) Create() {
cc.podName = cc.Container.Name + string(util.NewUUID())
imagePullSecrets := []api.LocalObjectReference{}
for _, s := range cc.ImagePullSecrets {
@@ -46,11 +45,9 @@ func (cc *ConformanceContainer) Create() error {
}
pod := &api.Pod{
ObjectMeta: api.ObjectMeta{
Name: cc.podName,
Namespace: cc.Namespace,
Name: cc.podName,
},
Spec: api.PodSpec{
NodeName: cc.NodeName,
RestartPolicy: cc.RestartPolicy,
Containers: []api.Container{
cc.Container,
@@ -59,17 +56,15 @@ func (cc *ConformanceContainer) Create() error {
ImagePullSecrets: imagePullSecrets,
},
}
_, err := cc.Client.Pods(cc.Namespace).Create(pod)
return err
cc.Framework.CreatePodAsync(pod)
}
func (cc *ConformanceContainer) Delete() error {
return cc.Client.Pods(cc.Namespace).Delete(cc.podName, api.NewDeleteOptions(0))
return cc.Framework.PodClient().Delete(cc.podName, api.NewDeleteOptions(0))
}
func (cc *ConformanceContainer) IsReady() (bool, error) {
pod, err := cc.Client.Pods(cc.Namespace).Get(cc.podName)
pod, err := cc.Framework.PodClient().Get(cc.podName)
if err != nil {
return false, err
}
@@ -77,7 +72,7 @@ func (cc *ConformanceContainer) IsReady() (bool, error) {
}
func (cc *ConformanceContainer) GetPhase() (api.PodPhase, error) {
pod, err := cc.Client.Pods(cc.Namespace).Get(cc.podName)
pod, err := cc.Framework.PodClient().Get(cc.podName)
if err != nil {
return api.PodUnknown, err
}
@@ -85,7 +80,7 @@ func (cc *ConformanceContainer) GetPhase() (api.PodPhase, error) {
}
func (cc *ConformanceContainer) GetStatus() (api.ContainerStatus, error) {
pod, err := cc.Client.Pods(cc.Namespace).Get(cc.podName)
pod, err := cc.Framework.PodClient().Get(cc.podName)
if err != nil {
return api.ContainerStatus{}, err
}
@@ -97,7 +92,7 @@ func (cc *ConformanceContainer) GetStatus() (api.ContainerStatus, error) {
}
func (cc *ConformanceContainer) Present() (bool, error) {
_, err := cc.Client.Pods(cc.Namespace).Get(cc.podName)
_, err := cc.Framework.PodClient().Get(cc.podName)
if err == nil {
return true, nil
}

View File

@@ -36,14 +36,11 @@ var _ = framework.KubeDescribe("Kubelet Container Manager", func() {
BeforeEach(func() {
podName = "bin-false" + string(util.NewUUID())
pod := &api.Pod{
f.CreatePodAsync(&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: podName,
Namespace: f.Namespace.Name,
Name: podName,
},
Spec: api.PodSpec{
// Force the Pod to schedule to the node without a scheduler running
NodeName: *nodeName,
// Don't restart the Pod since it is expected to exit
RestartPolicy: api.RestartPolicyNever,
Containers: []api.Container{
@@ -54,15 +51,12 @@ var _ = framework.KubeDescribe("Kubelet Container Manager", func() {
},
},
},
}
_, err := f.Client.Pods(f.Namespace.Name).Create(pod)
Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err))
})
})
It("should have an error terminated reason", func() {
Eventually(func() error {
podData, err := f.Client.Pods(f.Namespace.Name).Get(podName)
podData, err := f.PodClient().Get(podName)
if err != nil {
return err
}
@@ -81,7 +75,7 @@ var _ = framework.KubeDescribe("Kubelet Container Manager", func() {
})
It("should be possible to delete", func() {
err := f.Client.Pods(f.Namespace.Name).Delete(podName, &api.DeleteOptions{})
err := f.PodClient().Delete(podName, &api.DeleteOptions{})
Expect(err).To(BeNil(), fmt.Sprintf("Error deleting Pod %v", err))
})
})

View File

@@ -158,7 +158,7 @@ func testDownwardAPI(f *framework.Framework, podName string, env []api.EnvVar, e
RestartPolicy: api.RestartPolicyNever,
},
}
assignPodToNode(pod)
f.MungePodSpec(pod)
f.TestContainerOutputRegexp("downward api env vars", pod, 0, expectations)
}

View File

@@ -31,6 +31,8 @@ import (
"testing"
"time"
"k8s.io/kubernetes/test/e2e/framework"
"github.com/golang/glog"
. "github.com/onsi/ginkgo"
more_reporters "github.com/onsi/ginkgo/reporters"
@@ -42,6 +44,11 @@ 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 init() {
framework.RegisterCommonFlags()
framework.RegisterNodeFlags()
}
func TestE2eNode(t *testing.T) {
flag.Parse()
@@ -67,12 +74,12 @@ var _ = BeforeSuite(func() {
if *buildServices {
buildGo()
}
if *nodeName == "" {
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)
}
*nodeName = strings.TrimSpace(fmt.Sprintf("%s", 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
@@ -89,7 +96,7 @@ var _ = BeforeSuite(func() {
maskLocksmithdOnCoreos()
if *startServices {
e2es = newE2eService(*nodeName)
e2es = newE2eService(framework.TestContext.NodeName)
if err := e2es.start(); err != nil {
Fail(fmt.Sprintf("Unable to start node services.\n%v", err))
}

View File

@@ -42,14 +42,11 @@ var _ = framework.KubeDescribe("Kubelet", func() {
Context("when scheduling a busybox command in a pod", func() {
podName := "busybox-scheduling-" + string(util.NewUUID())
It("it should print the output to logs", func() {
podClient := f.Client.Pods(f.Namespace.Name)
pod := &api.Pod{
f.CreatePod(&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: podName,
},
Spec: api.PodSpec{
// Force the Pod to schedule to the node without a scheduler running
NodeName: *nodeName,
// Don't restart the Pod since it is expected to exit
RestartPolicy: api.RestartPolicyNever,
Containers: []api.Container{
@@ -60,14 +57,10 @@ var _ = framework.KubeDescribe("Kubelet", func() {
},
},
},
}
defer podClient.Delete(pod.Name, nil)
_, err := podClient.Create(pod)
Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err))
framework.ExpectNoError(f.WaitForPodRunning(pod.Name))
})
Eventually(func() string {
sinceTime := apiUnversioned.NewTime(time.Now().Add(time.Duration(-1 * time.Hour)))
rc, err := podClient.GetLogs(podName, &api.PodLogOptions{SinceTime: &sinceTime}).Stream()
rc, err := f.PodClient().GetLogs(podName, &api.PodLogOptions{SinceTime: &sinceTime}).Stream()
if err != nil {
return ""
}
@@ -82,15 +75,12 @@ var _ = framework.KubeDescribe("Kubelet", func() {
Context("when scheduling a read only busybox container", func() {
podName := "busybox-readonly-fs" + string(util.NewUUID())
It("it should not write to root filesystem", func() {
podClient := f.Client.Pods(f.Namespace.Name)
isReadOnly := true
pod := &api.Pod{
f.CreatePod(&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: podName,
},
Spec: api.PodSpec{
// Force the Pod to schedule to the node without a scheduler running
NodeName: *nodeName,
// Don't restart the Pod since it is expected to exit
RestartPolicy: api.RestartPolicyNever,
Containers: []api.Container{
@@ -104,12 +94,9 @@ var _ = framework.KubeDescribe("Kubelet", func() {
},
},
},
}
defer podClient.Delete(pod.Name, nil)
_, err := podClient.Create(pod)
Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err))
})
Eventually(func() string {
rc, err := podClient.GetLogs(podName, &api.PodLogOptions{}).Stream()
rc, err := f.PodClient().GetLogs(podName, &api.PodLogOptions{}).Stream()
if err != nil {
return ""
}
@@ -172,46 +159,38 @@ func createSummaryTestPods(f *framework.Framework, podNamePrefix string, count i
podNames.Insert(fmt.Sprintf("%s%v", podNamePrefix, i))
}
var pods []*api.Pod
for _, podName := range podNames.List() {
createPod(f, podName, []api.Container{
{
Image: ImageRegistry[busyBoxImage],
Command: []string{"sh", "-c", "while true; do echo 'hello world' | tee /test-empty-dir-mnt/file ; sleep 1; done"},
Name: podName + containerSuffix,
VolumeMounts: []api.VolumeMount{
{MountPath: "/test-empty-dir-mnt", Name: volumeNamePrefix},
pods = append(pods, &api.Pod{
ObjectMeta: api.ObjectMeta{
Name: podName,
},
Spec: api.PodSpec{
// Don't restart the Pod since it is expected to exit
RestartPolicy: api.RestartPolicyNever,
Containers: []api.Container{
{
Image: ImageRegistry[busyBoxImage],
Command: []string{"sh", "-c", "while true; do echo 'hello world' | tee /test-empty-dir-mnt/file ; sleep 1; done"},
Name: podName + containerSuffix,
VolumeMounts: []api.VolumeMount{
{MountPath: "/test-empty-dir-mnt", Name: volumeNamePrefix},
},
},
},
Volumes: []api.Volume{
// TODO: Test secret volumes
// TODO: Test hostpath volumes
{Name: volumeNamePrefix, VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
},
},
}, []api.Volume{
// TODO: Test secret volumes
// TODO: Test hostpath volumes
{Name: volumeNamePrefix, VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
})
}
f.CreatePods(pods)
return podNames, volumes
}
func createPod(f *framework.Framework, podName string, containers []api.Container, volumes []api.Volume) {
podClient := f.Client.Pods(f.Namespace.Name)
pod := &api.Pod{
ObjectMeta: api.ObjectMeta{
Name: podName,
},
Spec: api.PodSpec{
// Force the Pod to schedule to the node without a scheduler running
NodeName: *nodeName,
// Don't restart the Pod since it is expected to exit
RestartPolicy: api.RestartPolicyNever,
Containers: containers,
Volumes: volumes,
},
}
_, err := podClient.Create(pod)
Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err))
framework.ExpectNoError(f.WaitForPodRunning(pod.Name))
}
// Returns pods missing from summary.
func podsMissingFromSummary(s stats.Summary, expectedPods sets.String) sets.String {
expectedPods = sets.StringKeySet(expectedPods)
@@ -244,7 +223,7 @@ func testSummaryMetrics(s stats.Summary, podNamePrefix string) error {
nonNilValue = "expected %q to not be nil"
nonZeroValue = "expected %q to not be zero"
)
if s.Node.NodeName != *nodeName {
if s.Node.NodeName != framework.TestContext.NodeName {
return fmt.Errorf("unexpected node name - %q", s.Node.NodeName)
}
if s.Node.CPU.UsageCoreNanoSeconds == nil {

View File

@@ -27,6 +27,7 @@ import (
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/client/restclient"
client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/test/e2e/framework"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -211,7 +212,7 @@ func createPodAndWaitUntilRunning(c *client.Client, pod *api.Pod) *api.Pod {
func createPodWithSpec(c *client.Client, pod *api.Pod) (*api.Pod, error) {
// Manually assign pod to node because we don't run the scheduler in node
// e2e tests.
assignPodToNode(pod)
pod.Spec.NodeName = framework.TestContext.NodeName
createdPod, err := c.Pods(pod.Namespace).Create(pod)
return createdPod, err
}

View File

@@ -97,14 +97,12 @@ while true; do sleep 1; done
testContainer.Name = testCase.Name
testContainer.Command = []string{"sh", "-c", tmpCmd}
terminateContainer := ConformanceContainer{
Framework: f,
Container: testContainer,
Client: f.Client,
RestartPolicy: testCase.RestartPolicy,
Volumes: testVolumes,
NodeName: *nodeName,
Namespace: f.Namespace.Name,
}
Expect(terminateContainer.Create()).To(Succeed())
terminateContainer.Create()
defer terminateContainer.Delete()
By("it should get the expected 'RestartCount'")
@@ -136,6 +134,7 @@ while true; do sleep 1; done
terminationMessage := "DONE"
terminationMessagePath := "/dev/termination-log"
c := ConformanceContainer{
Framework: f,
Container: api.Container{
Image: ImageRegistry[busyBoxImage],
Name: name,
@@ -143,14 +142,11 @@ while true; do sleep 1; done
Args: []string{fmt.Sprintf("/bin/echo -n %s > %s", terminationMessage, terminationMessagePath)},
TerminationMessagePath: terminationMessagePath,
},
Client: f.Client,
RestartPolicy: api.RestartPolicyNever,
NodeName: *nodeName,
Namespace: f.Namespace.Name,
}
By("create the container")
Expect(c.Create()).To(Succeed())
c.Create()
defer c.Delete()
By("wait for the container to succeed")
@@ -236,6 +232,7 @@ while true; do sleep 1; done
name := "image-pull-test"
command := []string{"/bin/sh", "-c", "while true; do sleep 1; done"}
container := ConformanceContainer{
Framework: f,
Container: api.Container{
Name: name,
Image: testCase.image,
@@ -243,10 +240,7 @@ while true; do sleep 1; done
// PullAlways makes sure that the image will always be pulled even if it is present before the test.
ImagePullPolicy: api.PullAlways,
},
Client: f.Client,
RestartPolicy: api.RestartPolicyNever,
NodeName: *nodeName,
Namespace: f.Namespace.Name,
}
if testCase.secret {
secret.Name = "image-pull-secret-" + string(util.NewUUID())
@@ -258,7 +252,7 @@ while true; do sleep 1; done
}
By("create the container")
Expect(container.Create()).To(Succeed())
container.Create()
defer container.Delete()
By("check the pod phase")

View File

@@ -19,14 +19,13 @@ package e2e_node
import (
"flag"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/test/e2e/framework"
)
var kubeletAddress = flag.String("kubelet-address", "http://127.0.0.1:10255", "Host and port of the kubelet")
var apiServerAddress = flag.String("api-server-address", "http://127.0.0.1:8080", "Host and port of the api server")
var nodeName = flag.String("node-name", "", "Name of the node")
var buildServices = flag.Bool("build-services", true, "If true, build local executables")
var startServices = flag.Bool("start-services", true, "If true, start local node services")
var stopServices = flag.Bool("stop-services", true, "If true, stop local node services after running tests")
@@ -42,7 +41,3 @@ func NewDefaultFramework(baseName string) *framework.Framework {
ClientBurst: 100,
}, nil, f)
}
func assignPodToNode(pod *api.Pod) {
pod.Spec.NodeName = *nodeName
}