Change TestContainerOutput to use the framework pod client.

This commit is contained in:
Random-Liu 2016-07-20 11:03:05 -07:00
parent 472dcec7b2
commit 5c7ac701d3
10 changed files with 72 additions and 105 deletions

View File

@ -195,9 +195,9 @@ var _ = framework.KubeDescribe("ConfigMap", func() {
}, },
} }
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{ f.TestContainerOutput("consume configMaps", pod, 0, []string{
"CONFIG_DATA_1=value-1", "CONFIG_DATA_1=value-1",
}, f.Namespace.Name) })
}) })
It("should be consumable in multiple volumes in the same pod", func() { It("should be consumable in multiple volumes in the same pod", func() {
@ -272,9 +272,9 @@ var _ = framework.KubeDescribe("ConfigMap", func() {
}, },
} }
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{ f.TestContainerOutput("consume configMaps", pod, 0, []string{
"content of file \"/etc/configmap-volume/data-1\": value-1", "content of file \"/etc/configmap-volume/data-1\": value-1",
}, f.Namespace.Name) })
}) })
}) })
@ -357,9 +357,9 @@ func doConfigMapE2EWithoutMappings(f *framework.Framework, uid, fsGroup int64) {
pod.Spec.SecurityContext.FSGroup = &fsGroup pod.Spec.SecurityContext.FSGroup = &fsGroup
} }
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{ f.TestContainerOutput("consume configMaps", pod, 0, []string{
"content of file \"/etc/configmap-volume/data-1\": value-1", "content of file \"/etc/configmap-volume/data-1\": value-1",
}, f.Namespace.Name) })
} }
@ -433,7 +433,7 @@ func doConfigMapE2EWithMappings(f *framework.Framework, uid, fsGroup int64) {
pod.Spec.SecurityContext.FSGroup = &fsGroup pod.Spec.SecurityContext.FSGroup = &fsGroup
} }
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{ f.TestContainerOutput("consume configMaps", pod, 0, []string{
"content of file \"/etc/configmap-volume/path/to/data-2\": value-2", "content of file \"/etc/configmap-volume/path/to/data-2\": value-2",
}, f.Namespace.Name) })
} }

View File

@ -18,7 +18,6 @@ package e2e
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/util/uuid" "k8s.io/kubernetes/pkg/util/uuid"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
@ -27,27 +26,20 @@ import (
var _ = framework.KubeDescribe("Docker Containers", func() { var _ = framework.KubeDescribe("Docker Containers", func() {
f := framework.NewDefaultFramework("containers") f := framework.NewDefaultFramework("containers")
var c *client.Client
var ns string
BeforeEach(func() {
c = f.Client
ns = f.Namespace.Name
})
It("should use the image defaults if command and args are blank [Conformance]", func() { It("should use the image defaults if command and args are blank [Conformance]", func() {
framework.TestContainerOutput("use defaults", c, entrypointTestPod(), 0, []string{ f.TestContainerOutput("use defaults", entrypointTestPod(), 0, []string{
"[/ep default arguments]", "[/ep default arguments]",
}, ns) })
}) })
It("should be able to override the image's default arguments (docker cmd) [Conformance]", func() { It("should be able to override the image's default arguments (docker cmd) [Conformance]", func() {
pod := entrypointTestPod() pod := entrypointTestPod()
pod.Spec.Containers[0].Args = []string{"override", "arguments"} pod.Spec.Containers[0].Args = []string{"override", "arguments"}
framework.TestContainerOutput("override arguments", c, pod, 0, []string{ f.TestContainerOutput("override arguments", pod, 0, []string{
"[/ep override arguments]", "[/ep override arguments]",
}, ns) })
}) })
// Note: when you override the entrypoint, the image's arguments (docker cmd) // Note: when you override the entrypoint, the image's arguments (docker cmd)
@ -56,9 +48,9 @@ var _ = framework.KubeDescribe("Docker Containers", func() {
pod := entrypointTestPod() pod := entrypointTestPod()
pod.Spec.Containers[0].Command = []string{"/ep-2"} pod.Spec.Containers[0].Command = []string{"/ep-2"}
framework.TestContainerOutput("override command", c, pod, 0, []string{ f.TestContainerOutput("override command", pod, 0, []string{
"[/ep-2]", "[/ep-2]",
}, ns) })
}) })
It("should be able to override the image's default command and arguments [Conformance]", func() { It("should be able to override the image's default command and arguments [Conformance]", func() {
@ -66,9 +58,9 @@ var _ = framework.KubeDescribe("Docker Containers", func() {
pod.Spec.Containers[0].Command = []string{"/ep-2"} pod.Spec.Containers[0].Command = []string{"/ep-2"}
pod.Spec.Containers[0].Args = []string{"override", "arguments"} pod.Spec.Containers[0].Args = []string{"override", "arguments"}
framework.TestContainerOutput("override all", c, pod, 0, []string{ f.TestContainerOutput("override all", pod, 0, []string{
"[/ep-2 override arguments]", "[/ep-2 override arguments]",
}, ns) })
}) })
}) })

View File

@ -38,9 +38,9 @@ var _ = framework.KubeDescribe("Downward API volume", func() {
podName := "downwardapi-volume-" + string(uuid.NewUUID()) podName := "downwardapi-volume-" + string(uuid.NewUUID())
pod := downwardAPIVolumePodForSimpleTest(podName, "/etc/podname") pod := downwardAPIVolumePodForSimpleTest(podName, "/etc/podname")
framework.TestContainerOutput("downward API volume plugin", f.Client, pod, 0, []string{ f.TestContainerOutput("downward API volume plugin", pod, 0, []string{
fmt.Sprintf("%s\n", podName), fmt.Sprintf("%s\n", podName),
}, f.Namespace.Name) })
}) })
It("should provide podname as non-root with fsgroup [Feature:FSGroup]", func() { It("should provide podname as non-root with fsgroup [Feature:FSGroup]", func() {
@ -52,9 +52,9 @@ var _ = framework.KubeDescribe("Downward API volume", func() {
RunAsUser: &uid, RunAsUser: &uid,
FSGroup: &gid, FSGroup: &gid,
} }
framework.TestContainerOutput("downward API volume plugin", f.Client, pod, 0, []string{ f.TestContainerOutput("downward API volume plugin", pod, 0, []string{
fmt.Sprintf("%s\n", podName), fmt.Sprintf("%s\n", podName),
}, f.Namespace.Name) })
}) })
It("should update labels on modification [Conformance]", func() { It("should update labels on modification [Conformance]", func() {
@ -130,36 +130,36 @@ var _ = framework.KubeDescribe("Downward API volume", func() {
podName := "downwardapi-volume-" + string(uuid.NewUUID()) podName := "downwardapi-volume-" + string(uuid.NewUUID())
pod := downwardAPIVolumeForContainerResources(podName, "/etc/cpu_limit") pod := downwardAPIVolumeForContainerResources(podName, "/etc/cpu_limit")
framework.TestContainerOutput("downward API volume plugin", f.Client, pod, 0, []string{ f.TestContainerOutput("downward API volume plugin", pod, 0, []string{
fmt.Sprintf("2\n"), fmt.Sprintf("2\n"),
}, f.Namespace.Name) })
}) })
It("should provide container's memory limit", func() { It("should provide container's memory limit", func() {
podName := "downwardapi-volume-" + string(uuid.NewUUID()) podName := "downwardapi-volume-" + string(uuid.NewUUID())
pod := downwardAPIVolumeForContainerResources(podName, "/etc/memory_limit") pod := downwardAPIVolumeForContainerResources(podName, "/etc/memory_limit")
framework.TestContainerOutput("downward API volume plugin", f.Client, pod, 0, []string{ f.TestContainerOutput("downward API volume plugin", pod, 0, []string{
fmt.Sprintf("67108864\n"), fmt.Sprintf("67108864\n"),
}, f.Namespace.Name) })
}) })
It("should provide container's cpu request", func() { It("should provide container's cpu request", func() {
podName := "downwardapi-volume-" + string(uuid.NewUUID()) podName := "downwardapi-volume-" + string(uuid.NewUUID())
pod := downwardAPIVolumeForContainerResources(podName, "/etc/cpu_request") pod := downwardAPIVolumeForContainerResources(podName, "/etc/cpu_request")
framework.TestContainerOutput("downward API volume plugin", f.Client, pod, 0, []string{ f.TestContainerOutput("downward API volume plugin", pod, 0, []string{
fmt.Sprintf("1\n"), fmt.Sprintf("1\n"),
}, f.Namespace.Name) })
}) })
It("should provide container's memory request", func() { It("should provide container's memory request", func() {
podName := "downwardapi-volume-" + string(uuid.NewUUID()) podName := "downwardapi-volume-" + string(uuid.NewUUID())
pod := downwardAPIVolumeForContainerResources(podName, "/etc/memory_request") pod := downwardAPIVolumeForContainerResources(podName, "/etc/memory_request")
framework.TestContainerOutput("downward API volume plugin", f.Client, pod, 0, []string{ f.TestContainerOutput("downward API volume plugin", pod, 0, []string{
fmt.Sprintf("33554432\n"), fmt.Sprintf("33554432\n"),
}, f.Namespace.Name) })
}) })
}) })

View File

@ -373,14 +373,18 @@ func (f *Framework) WaitForPodNoLongerRunning(podName string) error {
return WaitForPodNoLongerRunningInNamespace(f.Client, podName, f.Namespace.Name, "") return WaitForPodNoLongerRunningInNamespace(f.Client, podName, f.Namespace.Name, "")
} }
// Runs the given pod and verifies that the output of exact container matches the desired output. // TestContainerOutput runs the given pod in the given namespace and waits
// for all of the containers in the podSpec to move into the 'Success' status, and tests
// the specified container log against the given expected output using a substring matcher.
func (f *Framework) TestContainerOutput(scenarioName string, pod *api.Pod, containerIndex int, expectedOutput []string) { func (f *Framework) TestContainerOutput(scenarioName string, pod *api.Pod, containerIndex int, expectedOutput []string) {
TestContainerOutput(scenarioName, f.Client, pod, containerIndex, expectedOutput, f.Namespace.Name) f.testContainerOutputMatcher(scenarioName, pod, containerIndex, expectedOutput, ContainSubstring)
} }
// Runs the given pod and verifies that the output of exact container matches the desired regexps. // TestContainerOutputRegexp runs the given pod in the given namespace and waits
// for all of the containers in the podSpec to move into the 'Success' status, and tests
// the specified container log against the given expected output using a regexp matcher.
func (f *Framework) TestContainerOutputRegexp(scenarioName string, pod *api.Pod, containerIndex int, expectedOutput []string) { func (f *Framework) TestContainerOutputRegexp(scenarioName string, pod *api.Pod, containerIndex int, expectedOutput []string) {
testContainerOutputRegexp(scenarioName, f.Client, pod, containerIndex, expectedOutput, f.Namespace.Name) f.testContainerOutputMatcher(scenarioName, pod, containerIndex, expectedOutput, MatchRegexp)
} }
// WaitForAnEndpoint waits for at least one endpoint to become available in the // WaitForAnEndpoint waits for at least one endpoint to become available in the

View File

@ -45,7 +45,7 @@ type PodClient struct {
// Create creates a new pod according to the framework specifications (don't wait for it to start). // Create creates a new pod according to the framework specifications (don't wait for it to start).
func (c *PodClient) Create(pod *api.Pod) *api.Pod { func (c *PodClient) Create(pod *api.Pod) *api.Pod {
c.MungeSpec(pod) c.mungeSpec(pod)
p, err := c.PodInterface.Create(pod) p, err := c.PodInterface.Create(pod)
ExpectNoError(err, "Error creating Pod") ExpectNoError(err, "Error creating Pod")
return p return p
@ -77,16 +77,6 @@ func (c *PodClient) CreateBatch(pods []*api.Pod) []*api.Pod {
return ps return ps
} }
// MungeSpec apply test-suite specific transformations to the pod spec.
// TODO: Refactor the framework to always use PodClient so that we can completely hide the munge logic
// in the PodClient.
func (c *PodClient) MungeSpec(pod *api.Pod) {
if TestContext.NodeName != "" {
Expect(pod.Spec.NodeName).To(Or(BeZero(), Equal(TestContext.NodeName)), "Test misconfigured")
pod.Spec.NodeName = TestContext.NodeName
}
}
// Update updates the pod object. It retries if there is a conflict, throw out error if // Update updates the pod object. It retries if there is a conflict, throw out error if
// there is any other errors. name is the pod name, updateFn is the function updating the // there is any other errors. name is the pod name, updateFn is the function updating the
// pod object. // pod object.
@ -110,4 +100,12 @@ func (c *PodClient) Update(name string, updateFn func(pod *api.Pod)) {
})) }))
} }
// mungeSpec apply test-suite specific transformations to the pod spec.
func (c *PodClient) mungeSpec(pod *api.Pod) {
if TestContext.NodeName != "" {
Expect(pod.Spec.NodeName).To(Or(BeZero(), Equal(TestContext.NodeName)), "Test misconfigured")
pod.Spec.NodeName = TestContext.NodeName
}
}
// TODO(random-liu): Move pod wait function into this file // TODO(random-liu): Move pod wait function into this file

View File

@ -2083,40 +2083,25 @@ func TryKill(cmd *exec.Cmd) {
} }
} }
// TestContainerOutput runs the given pod in the given namespace and waits
// for all of the containers in the podSpec to move into the 'Success' status, and tests
// the specified container log against the given expected output using a substring matcher.
func TestContainerOutput(scenarioName string, c *client.Client, pod *api.Pod, containerIndex int, expectedOutput []string, ns string) {
testContainerOutputMatcher(scenarioName, c, pod, containerIndex, expectedOutput, ns, ContainSubstring)
}
// testContainerOutputRegexp runs the given pod in the given namespace and waits
// for all of the containers in the podSpec to move into the 'Success' status, and tests
// the specified container log against the given expected output using a regexp matcher.
func testContainerOutputRegexp(scenarioName string, c *client.Client, pod *api.Pod, containerIndex int, expectedOutput []string, ns string) {
testContainerOutputMatcher(scenarioName, c, pod, containerIndex, expectedOutput, ns, MatchRegexp)
}
// testContainerOutputMatcher runs the given pod in the given namespace and waits // testContainerOutputMatcher runs the given pod in the given namespace and waits
// for all of the containers in the podSpec to move into the 'Success' status, and tests // for all of the containers in the podSpec to move into the 'Success' status, and tests
// the specified container log against the given expected output using the given matcher. // the specified container log against the given expected output using the given matcher.
func testContainerOutputMatcher(scenarioName string, func (f *Framework) testContainerOutputMatcher(scenarioName string,
c *client.Client,
pod *api.Pod, pod *api.Pod,
containerIndex int, containerIndex int,
expectedOutput []string, ns string, expectedOutput []string,
matcher func(string, ...interface{}) gomegatypes.GomegaMatcher) { matcher func(string, ...interface{}) gomegatypes.GomegaMatcher) {
By(fmt.Sprintf("Creating a pod to test %v", scenarioName)) By(fmt.Sprintf("Creating a pod to test %v", scenarioName))
podClient := f.PodClient()
ns := f.Namespace.Name
defer c.Pods(ns).Delete(pod.Name, api.NewDeleteOptions(0)) defer podClient.Delete(pod.Name, api.NewDeleteOptions(0))
if _, err := c.Pods(ns).Create(pod); err != nil { podClient.Create(pod)
Failf("Failed to create pod: %v", err)
}
// Wait for client pod to complete. // Wait for client pod to complete.
var containerName string var containerName string
for id, container := range pod.Spec.Containers { for id, container := range pod.Spec.Containers {
ExpectNoError(WaitForPodSuccessInNamespace(c, pod.Name, container.Name, ns)) ExpectNoError(WaitForPodSuccessInNamespace(f.Client, pod.Name, container.Name, ns))
if id == containerIndex { if id == containerIndex {
containerName = container.Name containerName = container.Name
} }
@ -2126,7 +2111,7 @@ func testContainerOutputMatcher(scenarioName string,
} }
// Grab its logs. Get host first. // Grab its logs. Get host first.
podStatus, err := c.Pods(ns).Get(pod.Name) podStatus, err := podClient.Get(pod.Name)
if err != nil { if err != nil {
Failf("Failed to get pod status: %v", err) Failf("Failed to get pod status: %v", err)
} }
@ -2139,7 +2124,7 @@ func testContainerOutputMatcher(scenarioName string,
// Sometimes the actual containers take a second to get started, try to get logs for 60s // Sometimes the actual containers take a second to get started, try to get logs for 60s
for time.Now().Sub(start) < (60 * time.Second) { for time.Now().Sub(start) < (60 * time.Second) {
err = nil err = nil
logs, err = GetPodLogs(c, ns, pod.Name, containerName) logs, err = GetPodLogs(f.Client, ns, pod.Name, containerName)
if err != nil { if err != nil {
By(fmt.Sprintf("Warning: Failed to get logs from node %q pod %q container %q. %v", By(fmt.Sprintf("Warning: Failed to get logs from node %q pod %q container %q. %v",
podStatus.Spec.NodeName, podStatus.Name, containerName, err)) podStatus.Spec.NodeName, podStatus.Name, containerName, err))

View File

@ -56,10 +56,9 @@ var _ = framework.KubeDescribe("hostPath", func() {
fmt.Sprintf("--fs_type=%v", volumePath), fmt.Sprintf("--fs_type=%v", volumePath),
fmt.Sprintf("--file_mode=%v", volumePath), fmt.Sprintf("--file_mode=%v", volumePath),
} }
framework.TestContainerOutput("hostPath mode", c, pod, 0, []string{ f.TestContainerOutput("hostPath mode", pod, 0, []string{
"mode of file \"/test-volume\": dtrwxrwxrwx", // we expect the sticky bit (mode flag t) to be set for the dir "mode of file \"/test-volume\": dtrwxrwxrwx", // we expect the sticky bit (mode flag t) to be set for the dir
}, })
namespace.Name)
}) })
// This test requires mounting a folder into a container with write privileges. // This test requires mounting a folder into a container with write privileges.
@ -83,10 +82,9 @@ var _ = framework.KubeDescribe("hostPath", func() {
} }
//Read the content of the file with the second container to //Read the content of the file with the second container to
//verify volumes being shared properly among containers within the pod. //verify volumes being shared properly among containers within the pod.
framework.TestContainerOutput("hostPath r/w", c, pod, 1, []string{ f.TestContainerOutput("hostPath r/w", pod, 1, []string{
"content of file \"/test-volume/test-file\": mount-tester new file", "content of file \"/test-volume/test-file\": mount-tester new file",
}, namespace.Name, })
)
}) })
It("should support subPath [Conformance]", func() { It("should support subPath [Conformance]", func() {
@ -115,9 +113,9 @@ var _ = framework.KubeDescribe("hostPath", func() {
fmt.Sprintf("--retry_time=%d", retryDuration), fmt.Sprintf("--retry_time=%d", retryDuration),
} }
framework.TestContainerOutput("hostPath subPath", c, pod, 1, []string{ f.TestContainerOutput("hostPath subPath", pod, 1, []string{
"content of file \"" + filePathInReader + "\": mount-tester new file", "content of file \"" + filePathInReader + "\": mount-tester new file",
}, namespace.Name) })
}) })
}) })

View File

@ -82,10 +82,10 @@ var _ = framework.KubeDescribe("Secrets", func() {
}, },
} }
framework.TestContainerOutput("consume secrets", f.Client, pod, 0, []string{ f.TestContainerOutput("consume secrets", pod, 0, []string{
"content of file \"/etc/secret-volume/data-1\": value-1", "content of file \"/etc/secret-volume/data-1\": value-1",
"mode of file \"/etc/secret-volume/data-1\": -rw-r--r--", "mode of file \"/etc/secret-volume/data-1\": -rw-r--r--",
}, f.Namespace.Name) })
}) })
It("should be consumable in multiple volumes in a pod [Conformance]", func() { It("should be consumable in multiple volumes in a pod [Conformance]", func() {
@ -161,10 +161,10 @@ var _ = framework.KubeDescribe("Secrets", func() {
}, },
} }
framework.TestContainerOutput("consume secrets", f.Client, pod, 0, []string{ f.TestContainerOutput("consume secrets", pod, 0, []string{
"content of file \"/etc/secret-volume/data-1\": value-1", "content of file \"/etc/secret-volume/data-1\": value-1",
"mode of file \"/etc/secret-volume/data-1\": -rw-r--r--", "mode of file \"/etc/secret-volume/data-1\": -rw-r--r--",
}, f.Namespace.Name) })
}) })
It("should be consumable from pods in env vars [Conformance]", func() { It("should be consumable from pods in env vars [Conformance]", func() {
@ -212,9 +212,9 @@ var _ = framework.KubeDescribe("Secrets", func() {
}, },
} }
framework.TestContainerOutput("consume secrets", f.Client, pod, 0, []string{ f.TestContainerOutput("consume secrets", pod, 0, []string{
"SECRET_DATA=value-1", "SECRET_DATA=value-1",
}, f.Namespace.Name) })
}) })
}) })

View File

@ -179,12 +179,9 @@ var _ = framework.KubeDescribe("ConfigMap", func() {
}, },
} }
// TODO(random-liu): Change TestContainerOutput to use PodClient and avoid MungeSpec explicitly f.TestContainerOutput("consume configMaps", pod, 0, []string{
f.PodClient().MungeSpec(pod)
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{
"CONFIG_DATA_1=value-1", "CONFIG_DATA_1=value-1",
}, f.Namespace.Name) })
}) })
}) })
@ -261,11 +258,9 @@ func doConfigMapE2EWithoutMappings(f *framework.Framework, uid, fsGroup int64) {
pod.Spec.SecurityContext.FSGroup = &fsGroup pod.Spec.SecurityContext.FSGroup = &fsGroup
} }
f.PodClient().MungeSpec(pod) f.TestContainerOutput("consume configMaps", pod, 0, []string{
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{
"content of file \"/etc/configmap-volume/data-1\": value-1", "content of file \"/etc/configmap-volume/data-1\": value-1",
}, f.Namespace.Name) })
} }
@ -334,9 +329,7 @@ func doConfigMapE2EWithMappings(f *framework.Framework, uid, fsGroup int64) {
pod.Spec.SecurityContext.FSGroup = &fsGroup pod.Spec.SecurityContext.FSGroup = &fsGroup
} }
f.PodClient().MungeSpec(pod) f.TestContainerOutput("consume configMaps", pod, 0, []string{
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{
"content of file \"/etc/configmap-volume/path/to/data-2\": value-2", "content of file \"/etc/configmap-volume/path/to/data-2\": value-2",
}, f.Namespace.Name) })
} }

View File

@ -158,8 +158,5 @@ func testDownwardAPI(f *framework.Framework, podName string, env []api.EnvVar, e
RestartPolicy: api.RestartPolicyNever, RestartPolicy: api.RestartPolicyNever,
}, },
} }
// TODO(random-liu): Change TestContainerOutputRegexp to use PodClient and avoid MungeSpec explicitly
f.PodClient().MungeSpec(pod)
f.TestContainerOutputRegexp("downward api env vars", pod, 0, expectations) f.TestContainerOutputRegexp("downward api env vars", pod, 0, expectations)
} }