From aa3bf1faacead494b2fcf439c66f4d6eb5144f9a Mon Sep 17 00:00:00 2001 From: liang chenye Date: Sat, 23 Apr 2016 10:50:02 +0800 Subject: [PATCH] refactor e2e_node conformance test Signed-off-by: liang chenye --- test/e2e_node/conformance_test.go | 184 ---------------------- test/e2e_node/container.go | 13 +- test/e2e_node/container_manager_test.go | 17 +- test/e2e_node/image.go | 4 + test/e2e_node/image_conformance_test.go | 138 ++++++++++++++++ test/e2e_node/runtime_conformance_test.go | 139 ++++++++++++++++ 6 files changed, 309 insertions(+), 186 deletions(-) delete mode 100644 test/e2e_node/conformance_test.go create mode 100644 test/e2e_node/image_conformance_test.go create mode 100644 test/e2e_node/runtime_conformance_test.go diff --git a/test/e2e_node/conformance_test.go b/test/e2e_node/conformance_test.go deleted file mode 100644 index e164ea70a1..0000000000 --- a/test/e2e_node/conformance_test.go +++ /dev/null @@ -1,184 +0,0 @@ -/* -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. -*/ - -package e2e_node - -import ( - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/restclient" - client "k8s.io/kubernetes/pkg/client/unversioned" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -const ( - retryTimeout = time.Minute * 4 - pollInterval = time.Second * 5 - imageRetryTimeout = time.Minute * 2 - imagePullInterval = time.Second * 15 -) - -var _ = Describe("Container Conformance Test", func() { - var cl *client.Client - - BeforeEach(func() { - // Setup the apiserver client - cl = client.NewOrDie(&restclient.Config{Host: *apiServerAddress}) - }) - - Describe("container conformance blackbox test", func() { - Context("when testing images that exist", func() { - var conformImages []ConformanceImage - conformImageTags := []string{ - "gcr.io/google_containers/node-conformance:v1", - "gcr.io/google_containers/node-conformance:v2", - "gcr.io/google_containers/node-conformance:v3", - "gcr.io/google_containers/node-conformance:v4", - } - // TODO(random-liu): Each It should be independent, we should not let them depend on - // each other. - It("should pull successfully [Conformance]", func() { - for _, imageTag := range conformImageTags { - image, _ := NewConformanceImage("docker", imageTag) - conformImages = append(conformImages, image) - } - for _, image := range conformImages { - // Pulling images from gcr.io is flaky, so retry failures - Eventually(func() error { - return image.Pull() - }, imageRetryTimeout, imagePullInterval).ShouldNot(HaveOccurred()) - present, err := image.Present() - Expect(err).ShouldNot(HaveOccurred()) - Expect(present).Should(BeTrue()) - } - }) - It("should list pulled images [Conformance]", func() { - image, _ := NewConformanceImage("docker", "") - tags, _ := image.List() - for _, tag := range conformImageTags { - Expect(tags).To(ContainElement(tag)) - } - }) - It("should remove successfully [Conformance]", func() { - for _, image := range conformImages { - err := image.Remove() - Expect(err).NotTo(HaveOccurred()) - present, err := image.Present() - Expect(err).NotTo(HaveOccurred()) - Expect(present).To(BeFalse()) - } - }) - }) - Context("when testing image that does not exist", func() { - It("should not pull successfully [Conformance]", func() { - invalidImageTags := []string{ - // nonexistent image registry - "foo.com/foo/foo", - // nonexistent image - "gcr.io/google_containers/not_exist", - // TODO(random-liu): Add test for image pulling credential - } - for _, invalidImageTag := range invalidImageTags { - invalidImage, _ := NewConformanceImage("docker", invalidImageTag) - By("start pulling image") - err := invalidImage.Pull() - Expect(err).Should(HaveOccurred()) - - By("check image present") - present, err := invalidImage.Present() - Expect(err).ShouldNot(HaveOccurred()) - Expect(present).To(BeFalse()) - - By("listing image") - tags, err := invalidImage.List() - Expect(err).ShouldNot(HaveOccurred()) - Expect(tags).NotTo(ContainElement(invalidImage)) - - By("removing image") - err = invalidImage.Remove() - Expect(err).Should(HaveOccurred()) - } - }) - }) - Context("when running a container that terminates", func() { - var terminateCase ConformanceContainer - It("should run successfully to completion [Conformance]", func() { - terminateCase = ConformanceContainer{ - Container: api.Container{ - Image: "gcr.io/google_containers/busybox", - Name: "busybox", - Command: []string{"sh", "-c", "env"}, - ImagePullPolicy: api.PullIfNotPresent, - }, - Client: cl, - Phase: api.PodSucceeded, - NodeName: *nodeName, - } - err := terminateCase.Create() - Expect(err).NotTo(HaveOccurred()) - - // TODO: Check that the container enters running state by sleeping in the container #23309 - Eventually(func() (api.PodPhase, error) { - pod, err := terminateCase.Get() - return pod.Phase, err - }, retryTimeout, pollInterval).Should(Equal(terminateCase.Phase)) - }) - It("should report its phase as 'succeeded' [Conformance]", func() { - ccontainer, err := terminateCase.Get() - Expect(err).NotTo(HaveOccurred()) - Expect(ccontainer).Should(CContainerEqual(terminateCase)) - }) - It("should be possible to delete [Conformance]", func() { - err := terminateCase.Delete() - Expect(err).NotTo(HaveOccurred()) - }) - }) - Context("when running a container with invalid image", func() { - var invalidImageCase ConformanceContainer - It("should not start successfully [Conformance]", func() { - invalidImageCase = ConformanceContainer{ - Container: api.Container{ - Image: "foo.com/foo/foo", - Name: "foo", - Command: []string{"foo", "'Should not work'"}, - ImagePullPolicy: api.PullIfNotPresent, - }, - Client: cl, - Phase: api.PodPending, - NodeName: *nodeName, - } - err := invalidImageCase.Create() - Expect(err).NotTo(HaveOccurred()) - Eventually(func() (api.PodPhase, error) { - pod, err := invalidImageCase.Get() - return pod.Phase, err - }, retryTimeout, pollInterval).Should(Equal(invalidImageCase.Phase)) - }) - It("should report its phase as 'pending' [Conformance]", func() { - ccontainer, err := invalidImageCase.Get() - Expect(err).NotTo(HaveOccurred()) - Expect(ccontainer).Should(CContainerEqual(invalidImageCase)) - }) - It("should be possible to delete [Conformance]", func() { - err := invalidImageCase.Delete() - Expect(err).NotTo(HaveOccurred()) - }) - }) - }) -}) diff --git a/test/e2e_node/container.go b/test/e2e_node/container.go index e5bf8febb6..3d6925f52d 100644 --- a/test/e2e_node/container.go +++ b/test/e2e_node/container.go @@ -21,6 +21,7 @@ import ( "fmt" "k8s.io/kubernetes/pkg/api" + apierrs "k8s.io/kubernetes/pkg/api/errors" client "k8s.io/kubernetes/pkg/client/unversioned" "github.com/onsi/gomega/format" @@ -100,5 +101,15 @@ func (cc *ConformanceContainer) Get() (ConformanceContainer, error) { if containers == nil || len(containers) != 1 { return ConformanceContainer{}, errors.New("Failed to get container") } - return ConformanceContainer{containers[0], cc.Client, pod.Status.Phase, cc.NodeName}, nil + return ConformanceContainer{containers[0], cc.Client, pod.Status.Phase, pod.Spec.NodeName}, nil +} + +func (cc *ConformanceContainer) Present() (bool, error) { + _, err := cc.Client.Pods(api.NamespaceDefault).Get(cc.Container.Name) + if err == nil { + return true, nil + } else if err != nil && apierrs.IsNotFound(err) { + return false, nil + } + return false, err } diff --git a/test/e2e_node/container_manager_test.go b/test/e2e_node/container_manager_test.go index 0ae0887556..d70fbd7277 100644 --- a/test/e2e_node/container_manager_test.go +++ b/test/e2e_node/container_manager_test.go @@ -21,6 +21,7 @@ import ( "time" "k8s.io/kubernetes/pkg/api" + apierrs "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/client/restclient" client "k8s.io/kubernetes/pkg/client/unversioned" @@ -38,7 +39,8 @@ var _ = Describe("Kubelet Container Manager", func() { namespace := "oom-adj" Context("when scheduling a busybox command that always fails in a pod", func() { podName := "bin-false" - It("it should return succes", func() { + + BeforeEach(func() { pod := &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: podName, @@ -58,6 +60,7 @@ var _ = Describe("Kubelet Container Manager", func() { }, }, } + _, err := cl.Pods(namespace).Create(pod) Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err)) }) @@ -86,6 +89,18 @@ var _ = Describe("Kubelet Container Manager", func() { err := cl.Pods(namespace).Delete(podName, &api.DeleteOptions{}) Expect(err).To(BeNil(), fmt.Sprintf("Error deleting Pod %v", err)) }) + + AfterEach(func() { + cl.Pods(namespace).Delete(podName, &api.DeleteOptions{}) + Eventually(func() bool { + _, err := cl.Pods(namespace).Get(podName) + if err != nil && apierrs.IsNotFound(err) { + return true + } + return false + }, time.Minute, time.Second*4).Should(BeTrue()) + }) + }) }) diff --git a/test/e2e_node/image.go b/test/e2e_node/image.go index f57fb57f03..7e32a10b5a 100644 --- a/test/e2e_node/image.go +++ b/test/e2e_node/image.go @@ -76,3 +76,7 @@ func (ci *ConformanceImage) List() ([]string, error) { func (ci *ConformanceImage) Remove() error { return ci.Runtime.RemoveImage(ci.Image) } + +func (ci *ConformanceImage) GetTag() string { + return ci.Image.Image +} diff --git a/test/e2e_node/image_conformance_test.go b/test/e2e_node/image_conformance_test.go new file mode 100644 index 0000000000..838145a490 --- /dev/null +++ b/test/e2e_node/image_conformance_test.go @@ -0,0 +1,138 @@ +/* +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. +*/ + +package e2e_node + +import ( + "time" + + "k8s.io/kubernetes/pkg/client/restclient" + client "k8s.io/kubernetes/pkg/client/unversioned" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +const ( + imageRetryTimeout = time.Minute * 2 + imagePullInterval = time.Second * 15 +) + +var _ = Describe("Container Conformance Test", func() { + var cl *client.Client + + BeforeEach(func() { + // Setup the apiserver client + cl = client.NewOrDie(&restclient.Config{Host: *apiServerAddress}) + }) + + Describe("image conformance blackbox test", func() { + Context("when testing images that exist", func() { + var conformImages []ConformanceImage + BeforeEach(func() { + existImageTags := []string{ + "gcr.io/google_containers/busybox:1.24", + "gcr.io/google_containers/mounttest:0.2", + } + for _, existImageTag := range existImageTags { + conformImage, _ := NewConformanceImage("docker", existImageTag) + // Pulling images from gcr.io is flaky, so retry failures + Eventually(func() error { + return conformImage.Pull() + }, imageRetryTimeout, imagePullInterval).ShouldNot(HaveOccurred()) + conformImages = append(conformImages, conformImage) + } + }) + + It("It should present successfully [Conformance]", func() { + for _, conformImage := range conformImages { + present, err := conformImage.Present() + Expect(err).ShouldNot(HaveOccurred()) + Expect(present).To(BeTrue()) + } + }) + + It("should list pulled images [Conformance]", func() { + image, _ := NewConformanceImage("docker", "") + tags, err := image.List() + Expect(err).ShouldNot(HaveOccurred()) + for _, conformImage := range conformImages { + Expect(tags).To(ContainElement(conformImage.GetTag())) + } + }) + + AfterEach(func() { + for _, conformImage := range conformImages { + conformImage.Remove() + } + conformImages = []ConformanceImage{} + }) + + }) + Context("when testing image that does not exist", func() { + var conformImages []ConformanceImage + BeforeEach(func() { + invalidImageTags := []string{ + // nonexistent image registry + "foo.com/foo/fooimage", + // nonexistent image + "gcr.io/google_containers/not_exist", + // TODO(random-liu): Add test for image pulling credential + } + for _, invalidImageTag := range invalidImageTags { + conformImage, _ := NewConformanceImage("docker", invalidImageTag) + // Pulling images from gcr.io is flaky, so retry to make sure failure is not caused by flaky. + Consistently(func() error { + return conformImage.Pull() + }, imageRetryTimeout, imagePullInterval).Should(HaveOccurred()) + conformImages = append(conformImages, conformImage) + } + }) + + It("it should not present images [Conformance]", func() { + for _, conformImage := range conformImages { + present, err := conformImage.Present() + Expect(err).ShouldNot(HaveOccurred()) + Expect(present).To(BeFalse()) + } + }) + + It("it should not list pulled images [Conformance]", func() { + image, _ := NewConformanceImage("docker", "") + tags, err := image.List() + Expect(err).ShouldNot(HaveOccurred()) + for _, conformImage := range conformImages { + Expect(tags).NotTo(ContainElement(conformImage.GetTag())) + } + }) + + It("it should not remove non-exist images [Conformance]", func() { + for _, conformImage := range conformImages { + err := conformImage.Remove() + Expect(err).Should(HaveOccurred()) + } + }) + + AfterEach(func() { + for _, conformImage := range conformImages { + conformImage.Remove() + } + conformImages = []ConformanceImage{} + }) + + }) + }) +}) diff --git a/test/e2e_node/runtime_conformance_test.go b/test/e2e_node/runtime_conformance_test.go new file mode 100644 index 0000000000..174c5bfb56 --- /dev/null +++ b/test/e2e_node/runtime_conformance_test.go @@ -0,0 +1,139 @@ +/* +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. +*/ + +package e2e_node + +import ( + "time" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/client/restclient" + client "k8s.io/kubernetes/pkg/client/unversioned" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +const ( + retryTimeout = time.Minute * 4 + pollInterval = time.Second * 5 +) + +var _ = Describe("Container Runtime Conformance Test", func() { + var cl *client.Client + + BeforeEach(func() { + // Setup the apiserver client + cl = client.NewOrDie(&restclient.Config{Host: *apiServerAddress}) + }) + + Describe("container conformance blackbox test", func() { + Context("when running a container that terminates", func() { + var containerCase ConformanceContainer + + BeforeEach(func() { + containerCase = ConformanceContainer{ + Container: api.Container{ + Image: "gcr.io/google_containers/busybox", + Name: "busybox", + Command: []string{"sh", "-c", "env"}, + ImagePullPolicy: api.PullIfNotPresent, + }, + Client: cl, + Phase: api.PodSucceeded, + NodeName: *nodeName, + } + err := containerCase.Create() + Expect(err).NotTo(HaveOccurred()) + }) + + It("it should report its phase as 'succeeded' and get a same container [Conformance]", func() { + var container ConformanceContainer + var err error + Eventually(func() api.PodPhase { + container, err = containerCase.Get() + return container.Phase + }, retryTimeout, pollInterval).Should(Equal(api.PodSucceeded)) + Expect(err).NotTo(HaveOccurred()) + Expect(container).Should(CContainerEqual(containerCase)) + }) + + It("it should be possible to delete [Conformance]", func() { + err := containerCase.Delete() + Expect(err).NotTo(HaveOccurred()) + Eventually(func() bool { + isPresent, err := containerCase.Present() + return err == nil && !isPresent + }, retryTimeout, pollInterval).Should(BeTrue()) + }) + + AfterEach(func() { + containerCase.Delete() + Eventually(func() bool { + isPresent, err := containerCase.Present() + return err == nil && !isPresent + }, retryTimeout, pollInterval).Should(BeTrue()) + }) + + }) + Context("when running a container with invalid image", func() { + var containerCase ConformanceContainer + BeforeEach(func() { + containerCase = ConformanceContainer{ + Container: api.Container{ + Image: "foo.com/foo/foo", + Name: "foo", + Command: []string{"foo", "'Should not work'"}, + ImagePullPolicy: api.PullIfNotPresent, + }, + Client: cl, + Phase: api.PodPending, + NodeName: *nodeName, + } + err := containerCase.Create() + Expect(err).NotTo(HaveOccurred()) + }) + + It("it should report its phase as 'pending' and get a same container [Conformance]", func() { + var container ConformanceContainer + var err error + Consistently(func() api.PodPhase { + container, err = containerCase.Get() + return container.Phase + }, retryTimeout, pollInterval).Should(Equal(api.PodPending)) + Expect(err).NotTo(HaveOccurred()) + Expect(container).Should(CContainerEqual(containerCase)) + }) + + It("it should be possible to delete [Conformance]", func() { + err := containerCase.Delete() + Expect(err).NotTo(HaveOccurred()) + Eventually(func() bool { + isPresent, err := containerCase.Present() + return err == nil && !isPresent + }, retryTimeout, pollInterval).Should(BeTrue()) + }) + + AfterEach(func() { + containerCase.Delete() + Eventually(func() bool { + isPresent, err := containerCase.Present() + return err == nil && !isPresent + }, retryTimeout, pollInterval).Should(BeTrue()) + }) + }) + }) +})