From a6a3ed210c982ddbf1c61c7c2e7225d509af7f61 Mon Sep 17 00:00:00 2001 From: Yu-Ju Hong Date: Fri, 3 Jun 2016 18:10:33 -0700 Subject: [PATCH] Port the downward api test to the node e2e suite Also extend the framework to allow a custom client config loading function, so that the node e2e suite can reuse the same framework across tests. --- test/e2e/framework/framework.go | 14 ++- test/e2e/framework/util.go | 2 + test/e2e_node/downward_api_test.go | 164 +++++++++++++++++++++++++++++ test/e2e_node/privileged_test.go | 7 +- test/e2e_node/util.go | 20 ++-- 5 files changed, 191 insertions(+), 16 deletions(-) create mode 100644 test/e2e_node/downward_api_test.go diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index 9e9c76e1fcc..d427884d196 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -51,9 +51,10 @@ const ( type Framework struct { BaseName string - Client *client.Client - Clientset_1_2 *release_1_2.Clientset - Clientset_1_3 *release_1_3.Clientset + ClientConfigGetter ClientConfigGetter + Client *client.Client + Clientset_1_2 *release_1_2.Clientset + Clientset_1_3 *release_1_3.Clientset FederationClient *unversionedfederation.FederationClient @@ -110,11 +111,16 @@ func NewDefaultFederatedFramework(baseName string) *Framework { } func NewFramework(baseName string, options FrameworkOptions, client *client.Client) *Framework { + return NewFrameworkWithConfigGetter(baseName, options, client, LoadConfig) +} + +func NewFrameworkWithConfigGetter(baseName string, options FrameworkOptions, client *client.Client, configGetter ClientConfigGetter) *Framework { f := &Framework{ BaseName: baseName, AddonResourceConstraints: make(map[string]ResourceConstraint), options: options, Client: client, + ClientConfigGetter: configGetter, } BeforeEach(f.BeforeEach) @@ -130,7 +136,7 @@ func (f *Framework) BeforeEach() { f.cleanupHandle = AddCleanupAction(f.AfterEach) if f.Client == nil { By("Creating a kubernetes client") - config, err := LoadConfig() + config, err := f.ClientConfigGetter() Expect(err).NotTo(HaveOccurred()) config.QPS = f.options.ClientQPS config.Burst = f.options.ClientBurst diff --git a/test/e2e/framework/util.go b/test/e2e/framework/util.go index 66c2ae6e454..240e84a4690 100644 --- a/test/e2e/framework/util.go +++ b/test/e2e/framework/util.go @@ -1596,6 +1596,8 @@ func restclientConfig(kubeContext string) (*clientcmdapi.Config, error) { return c, nil } +type ClientConfigGetter func() (*restclient.Config, error) + func LoadConfig() (*restclient.Config, error) { c, err := restclientConfig(TestContext.KubeContext) if err != nil { diff --git a/test/e2e_node/downward_api_test.go b/test/e2e_node/downward_api_test.go new file mode 100644 index 00000000000..0c9c88ebb0b --- /dev/null +++ b/test/e2e_node/downward_api_test.go @@ -0,0 +1,164 @@ +/* +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 ( + "fmt" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/resource" + "k8s.io/kubernetes/pkg/util" + "k8s.io/kubernetes/test/e2e/framework" + + . "github.com/onsi/ginkgo" +) + +// Ported from test/e2e/downard_api_test.go + +var _ = framework.KubeDescribe("Downward API", func() { + f := NewDefaultFramework("downward-api") + It("should provide pod name and namespace as env vars [Conformance]", func() { + podName := "downward-api-" + string(util.NewUUID()) + env := []api.EnvVar{ + { + Name: "POD_NAME", + ValueFrom: &api.EnvVarSource{ + FieldRef: &api.ObjectFieldSelector{ + APIVersion: "v1", + FieldPath: "metadata.name", + }, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &api.EnvVarSource{ + FieldRef: &api.ObjectFieldSelector{ + APIVersion: "v1", + FieldPath: "metadata.namespace", + }, + }, + }, + } + + expectations := []string{ + fmt.Sprintf("POD_NAME=%v", podName), + fmt.Sprintf("POD_NAMESPACE=%v", f.Namespace.Name), + } + + testDownwardAPI(f, podName, env, expectations) + }) + + It("should provide pod IP as an env var", func() { + podName := "downward-api-" + string(util.NewUUID()) + env := []api.EnvVar{ + { + Name: "POD_IP", + ValueFrom: &api.EnvVarSource{ + FieldRef: &api.ObjectFieldSelector{ + APIVersion: "v1", + FieldPath: "status.podIP", + }, + }, + }, + } + + expectations := []string{ + "POD_IP=(?:\\d+)\\.(?:\\d+)\\.(?:\\d+)\\.(?:\\d+)", + } + + testDownwardAPI(f, podName, env, expectations) + }) + + It("should provide container's limits.cpu/memory and requests.cpu/memory as env vars", func() { + podName := "downward-api-" + string(util.NewUUID()) + env := []api.EnvVar{ + { + Name: "CPU_LIMIT", + ValueFrom: &api.EnvVarSource{ + ResourceFieldRef: &api.ResourceFieldSelector{ + Resource: "limits.cpu", + }, + }, + }, + { + Name: "MEMORY_LIMIT", + ValueFrom: &api.EnvVarSource{ + ResourceFieldRef: &api.ResourceFieldSelector{ + Resource: "limits.memory", + }, + }, + }, + { + Name: "CPU_REQUEST", + ValueFrom: &api.EnvVarSource{ + ResourceFieldRef: &api.ResourceFieldSelector{ + Resource: "requests.cpu", + }, + }, + }, + { + Name: "MEMORY_REQUEST", + ValueFrom: &api.EnvVarSource{ + ResourceFieldRef: &api.ResourceFieldSelector{ + Resource: "requests.memory", + }, + }, + }, + } + expectations := []string{ + fmt.Sprintf("CPU_LIMIT=2"), + fmt.Sprintf("MEMORY_LIMIT=67108864"), + fmt.Sprintf("CPU_REQUEST=1"), + fmt.Sprintf("MEMORY_REQUEST=33554432"), + } + + testDownwardAPI(f, podName, env, expectations) + }) +}) + +func testDownwardAPI(f *framework.Framework, podName string, env []api.EnvVar, expectations []string) { + pod := &api.Pod{ + ObjectMeta: api.ObjectMeta{ + Name: podName, + Labels: map[string]string{"name": podName}, + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: "dapi-container", + Image: "gcr.io/google_containers/busybox:1.24", + Command: []string{"sh", "-c", "env"}, + Resources: api.ResourceRequirements{ + Requests: api.ResourceList{ + api.ResourceCPU: resource.MustParse("250m"), + api.ResourceMemory: resource.MustParse("32Mi"), + }, + Limits: api.ResourceList{ + api.ResourceCPU: resource.MustParse("1250m"), + api.ResourceMemory: resource.MustParse("64Mi"), + }, + }, + Env: env, + }, + }, + RestartPolicy: api.RestartPolicyNever, + }, + } + assignPodToNode(pod) + + f.TestContainerOutputRegexp("downward api env vars", pod, 0, expectations) +} diff --git a/test/e2e_node/privileged_test.go b/test/e2e_node/privileged_test.go index 7c052f14560..b3194cf4663 100644 --- a/test/e2e_node/privileged_test.go +++ b/test/e2e_node/privileged_test.go @@ -197,10 +197,6 @@ func waitForPodRunning(c *client.Client, ns string, name string) error { return fmt.Errorf("Time out while waiting for pod %s/%s to become running; current status: %+v", ns, name, pod.Status) } -func setNodeNameForPod(pod *api.Pod) { - pod.Spec.NodeName = *nodeName -} - func createPodAndWaitUntilRunning(c *client.Client, pod *api.Pod) *api.Pod { ref := fmt.Sprintf("%v/%v", pod.Namespace, pod.Name) _, err := createPodWithSpec(c, pod) @@ -215,8 +211,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. - // TODO: This should also be a shared utility function. - setNodeNameForPod(pod) + assignPodToNode(pod) createdPod, err := c.Pods(pod.Namespace).Create(pod) return createdPod, err } diff --git a/test/e2e_node/util.go b/test/e2e_node/util.go index 3bd0a73eda8..d9f4149fd6c 100644 --- a/test/e2e_node/util.go +++ b/test/e2e_node/util.go @@ -19,8 +19,8 @@ package e2e_node import ( "flag" + "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/client/restclient" - client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/test/e2e/framework" ) @@ -32,9 +32,17 @@ var startServices = flag.Bool("start-services", true, "If true, start local node var stopServices = flag.Bool("stop-services", true, "If true, stop local node services after running tests") func NewDefaultFramework(baseName string) *framework.Framework { - client := client.NewOrDie(&restclient.Config{Host: *apiServerAddress}) - return framework.NewFramework(baseName, framework.FrameworkOptions{ - ClientQPS: 100, - ClientBurst: 100, - }, client) + // Provides a client config for the framework to create a client. + f := func() (*restclient.Config, error) { + return &restclient.Config{Host: *apiServerAddress}, nil + } + return framework.NewFrameworkWithConfigGetter(baseName, + framework.FrameworkOptions{ + ClientQPS: 100, + ClientBurst: 100, + }, nil, f) +} + +func assignPodToNode(pod *api.Pod) { + pod.Spec.NodeName = *nodeName }