diff --git a/pkg/client/unversioned/adapters/release_1_3/clientset_adaption.go b/pkg/client/unversioned/adapters/release_1_3/clientset_adaption.go new file mode 100644 index 0000000000..3f4b86fb4b --- /dev/null +++ b/pkg/client/unversioned/adapters/release_1_3/clientset_adaption.go @@ -0,0 +1,50 @@ +/* +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 release_1_3 + +import ( + "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3" + v1core "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3/typed/core/v1" + v1beta1extensions "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3/typed/extensions/v1beta1" + "k8s.io/kubernetes/pkg/client/typed/discovery" + "k8s.io/kubernetes/pkg/client/unversioned" +) + +// FromUnversionedClient adapts a unversioned.Client to a release_1_3.Clientset. +// This function is temporary. We will remove it when everyone has moved to using +// Clientset. New code should NOT use this function. +func FromUnversionedClient(c *unversioned.Client) *release_1_3.Clientset { + var clientset release_1_3.Clientset + if c != nil { + clientset.CoreClient = v1core.New(c.RESTClient) + } else { + clientset.CoreClient = v1core.New(nil) + } + if c != nil && c.ExtensionsClient != nil { + clientset.ExtensionsClient = v1beta1extensions.New(c.ExtensionsClient.RESTClient) + } else { + clientset.ExtensionsClient = v1beta1extensions.New(nil) + } + + if c != nil && c.DiscoveryClient != nil { + clientset.DiscoveryClient = discovery.NewDiscoveryClient(c.DiscoveryClient.RESTClient) + } else { + clientset.DiscoveryClient = discovery.NewDiscoveryClient(nil) + } + + return &clientset +} diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index 7238c51fef..97794eedec 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -27,8 +27,10 @@ import ( "k8s.io/kubernetes/pkg/api" apierrs "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2" + "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3" client "k8s.io/kubernetes/pkg/client/unversioned" - adapter "k8s.io/kubernetes/pkg/client/unversioned/adapters/release_1_2" + adapter_1_2 "k8s.io/kubernetes/pkg/client/unversioned/adapters/release_1_2" + adapter_1_3 "k8s.io/kubernetes/pkg/client/unversioned/adapters/release_1_3" "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/metrics" @@ -47,6 +49,7 @@ type Framework struct { Client *client.Client Clientset_1_2 *release_1_2.Clientset + Clientset_1_3 *release_1_3.Clientset Namespace *api.Namespace // Every test has at least one namespace namespacesToDelete []*api.Namespace // Some tests have more than one. @@ -119,7 +122,8 @@ func (f *Framework) BeforeEach() { Expect(err).NotTo(HaveOccurred()) f.Client = c - f.Clientset_1_2 = adapter.FromUnversionedClient(c) + f.Clientset_1_2 = adapter_1_2.FromUnversionedClient(c) + f.Clientset_1_3 = adapter_1_3.FromUnversionedClient(c) By("Building a namespace api object") namespace, err := f.CreateNamespace(f.BaseName, map[string]string{ diff --git a/test/e2e/generated_clientset.go b/test/e2e/generated_clientset.go index bc24c67c87..952bcc18f7 100644 --- a/test/e2e/generated_clientset.go +++ b/test/e2e/generated_clientset.go @@ -33,41 +33,77 @@ import ( . "github.com/onsi/gomega" ) +func testingPod(name, value string) v1.Pod { + return v1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + "name": "foo", + "time": value, + }, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "nginx", + Image: "gcr.io/google_containers/nginx:1.7.9", + Ports: []v1.ContainerPort{{ContainerPort: 80}}, + LivenessProbe: &v1.Probe{ + Handler: v1.Handler{ + HTTPGet: &v1.HTTPGetAction{ + Path: "/index.html", + Port: intstr.FromInt(8080), + }, + }, + InitialDelaySeconds: 30, + }, + }, + }, + }, + } +} + +func observePodCreation(w watch.Interface) { + select { + case event, _ := <-w.ResultChan(): + if event.Type != watch.Added { + framework.Failf("Failed to observe pod creation: %v", event) + } + case <-time.After(framework.PodStartTimeout): + Fail("Timeout while waiting for pod creation") + } +} + +func observePodDeletion(w watch.Interface) (lastPod *api.Pod) { + deleted := false + timeout := false + timer := time.After(60 * time.Second) + for !deleted && !timeout { + select { + case event, _ := <-w.ResultChan(): + if event.Type == watch.Deleted { + lastPod = event.Object.(*api.Pod) + deleted = true + } + case <-timer: + timeout = true + } + } + if !deleted { + Fail("Failed to observe pod deletion") + } + return +} + var _ = framework.KubeDescribe("Generated release_1_2 clientset", func() { f := framework.NewDefaultFramework("clientset") It("should create pods, delete pods, watch pods", func() { podClient := f.Clientset_1_2.Core().Pods(f.Namespace.Name) - By("creating the pod") + By("constructing the pod") name := "pod" + string(util.NewUUID()) value := strconv.Itoa(time.Now().Nanosecond()) - pod := &v1.Pod{ - ObjectMeta: v1.ObjectMeta{ - Name: name, - Labels: map[string]string{ - "name": "foo", - "time": value, - }, - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "nginx", - Image: "gcr.io/google_containers/nginx:1.7.9", - Ports: []v1.ContainerPort{{ContainerPort: 80}}, - LivenessProbe: &v1.Probe{ - Handler: v1.Handler{ - HTTPGet: &v1.HTTPGetAction{ - Path: "/index.html", - Port: intstr.FromInt(8080), - }, - }, - InitialDelaySeconds: 30, - }, - }, - }, - }, - } - + podCopy := testingPod(name, value) + pod := &podCopy By("setting up watch") selector := labels.SelectorFromSet(labels.Set(map[string]string{"time": value})) options := api.ListOptions{LabelSelector: selector} @@ -85,18 +121,17 @@ var _ = framework.KubeDescribe("Generated release_1_2 clientset", func() { framework.Failf("Failed to set up watch: %v", err) } - By("submitting the pod to kubernetes") - // We call defer here in case there is a problem with - // the test so we can ensure that we clean up after - // ourselves - defer podClient.Delete(pod.Name, api.NewDeleteOptions(0)) + By("creating the pod") pod, err = podClient.Create(pod) if err != nil { framework.Failf("Failed to create pod: %v", err) } + // We call defer here in case there is a problem with + // the test so we can ensure that we clean up after + // ourselves + defer podClient.Delete(pod.Name, api.NewDeleteOptions(0)) By("verifying the pod is in kubernetes") - selector = labels.SelectorFromSet(labels.Set(map[string]string{"time": value})) options = api.ListOptions{ LabelSelector: selector, ResourceVersion: pod.ResourceVersion, @@ -108,14 +143,7 @@ var _ = framework.KubeDescribe("Generated release_1_2 clientset", func() { Expect(len(pods.Items)).To(Equal(1)) By("verifying pod creation was observed") - select { - case event, _ := <-w.ResultChan(): - if event.Type != watch.Added { - framework.Failf("Failed to observe pod creation: %v", event) - } - case <-time.After(framework.PodStartTimeout): - Fail("Timeout while waiting for pod creation") - } + observePodCreation(w) // We need to wait for the pod to be scheduled, otherwise the deletion // will be carried out immediately rather than gracefully. @@ -127,31 +155,83 @@ var _ = framework.KubeDescribe("Generated release_1_2 clientset", func() { } By("verifying pod deletion was observed") - deleted := false - timeout := false - var lastPod *api.Pod - // The 30s grace period is not an upper-bound of the time it takes to - // delete the pod from etcd. - timer := time.After(60 * time.Second) - for !deleted && !timeout { - select { - case event, _ := <-w.ResultChan(): - if event.Type == watch.Deleted { - lastPod = event.Object.(*api.Pod) - deleted = true - } - case <-timer: - timeout = true - } - } - if !deleted { - Fail("Failed to observe pod deletion") - } - + lastPod := observePodDeletion(w) + Expect(lastPod.DeletionTimestamp).ToNot(BeNil()) + Expect(lastPod.Spec.TerminationGracePeriodSeconds).ToNot(BeZero()) + + options = api.ListOptions{LabelSelector: selector} + pods, err = podClient.List(options) + if err != nil { + Fail(fmt.Sprintf("Failed to list pods to verify deletion: %v", err)) + } + Expect(len(pods.Items)).To(Equal(0)) + }) +}) + +var _ = framework.KubeDescribe("Generated release_1_3 clientset", func() { + f := framework.NewDefaultFramework("clientset") + It("should create pods, delete pods, watch pods", func() { + podClient := f.Clientset_1_3.Core().Pods(f.Namespace.Name) + By("constructing the pod") + name := "pod" + string(util.NewUUID()) + value := strconv.Itoa(time.Now().Nanosecond()) + podCopy := testingPod(name, value) + pod := &podCopy + By("setting up watch") + selector := labels.SelectorFromSet(labels.Set(map[string]string{"time": value})) + options := api.ListOptions{LabelSelector: selector} + pods, err := podClient.List(options) + if err != nil { + framework.Failf("Failed to query for pods: %v", err) + } + Expect(len(pods.Items)).To(Equal(0)) + options = api.ListOptions{ + LabelSelector: selector, + ResourceVersion: pods.ListMeta.ResourceVersion, + } + w, err := podClient.Watch(options) + if err != nil { + framework.Failf("Failed to set up watch: %v", err) + } + + By("creating the pod") + pod, err = podClient.Create(pod) + if err != nil { + framework.Failf("Failed to create pod: %v", err) + } + // We call defer here in case there is a problem with + // the test so we can ensure that we clean up after + // ourselves + defer podClient.Delete(pod.Name, api.NewDeleteOptions(0)) + + By("verifying the pod is in kubernetes") + options = api.ListOptions{ + LabelSelector: selector, + ResourceVersion: pod.ResourceVersion, + } + pods, err = podClient.List(options) + if err != nil { + framework.Failf("Failed to query for pods: %v", err) + } + Expect(len(pods.Items)).To(Equal(1)) + + By("verifying pod creation was observed") + observePodCreation(w) + + // We need to wait for the pod to be scheduled, otherwise the deletion + // will be carried out immediately rather than gracefully. + framework.ExpectNoError(f.WaitForPodRunning(pod.Name)) + + By("deleting the pod gracefully") + if err := podClient.Delete(pod.Name, api.NewDeleteOptions(30)); err != nil { + framework.Failf("Failed to delete pod: %v", err) + } + + By("verifying pod deletion was observed") + lastPod := observePodDeletion(w) Expect(lastPod.DeletionTimestamp).ToNot(BeNil()) Expect(lastPod.Spec.TerminationGracePeriodSeconds).ToNot(BeZero()) - selector = labels.SelectorFromSet(labels.Set(map[string]string{"time": value})) options = api.ListOptions{LabelSelector: selector} pods, err = podClient.List(options) if err != nil {