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
commit 331fde8363
12 changed files with 166 additions and 119 deletions

View File

@ -23,7 +23,8 @@ import (
) )
func init() { func init() {
framework.RegisterFlags() framework.RegisterCommonFlags()
framework.RegisterClusterFlags()
} }
func TestE2E(t *testing.T) { func TestE2E(t *testing.T) {

View File

@ -0,0 +1,72 @@
/*
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 framework
import (
"sync"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned"
. "github.com/onsi/gomega"
)
// TODO: Consolidate pod-specific framework functions here.
// Convenience method for getting a pod client interface in the framework's namespace.
func (f *Framework) PodClient() unversioned.PodInterface {
return f.Client.Pods(f.Namespace.Name)
}
// Create a new pod according to the framework specifications, and wait for it to start.
func (f *Framework) CreatePod(pod *api.Pod) {
f.CreatePodAsync(pod)
ExpectNoError(f.WaitForPodRunning(pod.Name))
}
// Create a new pod according to the framework specifications (don't wait for it to start).
func (f *Framework) CreatePodAsync(pod *api.Pod) {
f.MungePodSpec(pod)
_, err := f.PodClient().Create(pod)
ExpectNoError(err, "Error creating Pod")
}
// Batch version of CreatePod. All pods are created before waiting.
func (f *Framework) CreatePods(pods []*api.Pod) {
for _, pod := range pods {
f.CreatePodAsync(pod)
}
var wg sync.WaitGroup
for _, pod := range pods {
wg.Add(1)
podName := pod.Name
go func() {
ExpectNoError(f.WaitForPodRunning(podName))
wg.Done()
}()
}
wg.Wait()
}
// Apply test-suite specific transformations to the pod spec.
// TODO: figure out a nicer, more generic way to tie this to framework instances.
func (f *Framework) MungePodSpec(pod *api.Pod) {
if TestContext.NodeName != "" {
Expect(pod.Spec.NodeName).To(Or(BeZero(), Equal(TestContext.NodeName)), "Test misconfigured")
pod.Spec.NodeName = TestContext.NodeName
}
}

View File

@ -65,6 +65,8 @@ type TestContextType struct {
CreateTestingNS CreateTestingNSFn CreateTestingNS CreateTestingNSFn
// If set to true test will dump data about the namespace in which test was running. // If set to true test will dump data about the namespace in which test was running.
DumpLogsOnFailure bool DumpLogsOnFailure bool
// Name of the node to run tests on (node e2e suite only).
NodeName string
} }
type CloudConfig struct { type CloudConfig struct {
@ -83,7 +85,8 @@ type CloudConfig struct {
var TestContext TestContextType var TestContext TestContextType
var federatedKubeContext string var federatedKubeContext string
func RegisterFlags() { // Register flags common to all e2e test suites.
func RegisterCommonFlags() {
// Turn on verbose by default to get spec names // Turn on verbose by default to get spec names
config.DefaultReporterConfig.Verbose = true config.DefaultReporterConfig.Verbose = true
@ -93,6 +96,19 @@ func RegisterFlags() {
// Randomize specs as well as suites // Randomize specs as well as suites
config.GinkgoConfig.RandomizeAllSpecs = true config.GinkgoConfig.RandomizeAllSpecs = true
flag.StringVar(&TestContext.GatherKubeSystemResourceUsageData, "gather-resource-usage", "false", "If set to 'true' or 'all' framework will be monitoring resource usage of system all add-ons in (some) e2e tests, if set to 'master' framework will be monitoring master node only, if set to 'none' of 'false' monitoring will be turned off.")
flag.BoolVar(&TestContext.GatherLogsSizes, "gather-logs-sizes", false, "If set to true framework will be monitoring logs sizes on all machines running e2e tests.")
flag.BoolVar(&TestContext.GatherMetricsAfterTest, "gather-metrics-at-teardown", false, "If set to true framwork will gather metrics from all components after each test.")
flag.StringVar(&TestContext.OutputPrintType, "output-print-type", "hr", "Comma separated list: 'hr' for human readable summaries 'json' for JSON ones.")
flag.BoolVar(&TestContext.DumpLogsOnFailure, "dump-logs-on-failure", true, "If set to true test will dump data about the namespace in which test was running.")
}
// Register flags specific to the cluster e2e test suite.
func RegisterClusterFlags() {
// TODO: Move to common flags once namespace deletion is fixed for node e2e.
flag.BoolVar(&TestContext.DeleteNamespace, "delete-namespace", true, "If true tests will delete namespace after completion. It is only designed to make debugging easier, DO NOT turn it off by default.")
flag.BoolVar(&TestContext.VerifyServiceAccount, "e2e-verify-service-account", true, "If true tests will verify the service account before running.")
flag.StringVar(&TestContext.KubeConfig, clientcmd.RecommendedConfigPathFlag, os.Getenv(clientcmd.RecommendedConfigPathEnvVar), "Path to kubeconfig containing embedded authinfo.") flag.StringVar(&TestContext.KubeConfig, clientcmd.RecommendedConfigPathFlag, os.Getenv(clientcmd.RecommendedConfigPathEnvVar), "Path to kubeconfig containing embedded authinfo.")
flag.StringVar(&TestContext.KubeContext, clientcmd.FlagContext, "", "kubeconfig context to use/override. If unset, will use value from 'current-context'") flag.StringVar(&TestContext.KubeContext, clientcmd.FlagContext, "", "kubeconfig context to use/override. If unset, will use value from 'current-context'")
flag.StringVar(&TestContext.KubeAPIContentType, "kube-api-content-type", "", "ContentType used to communicate with apiserver") flag.StringVar(&TestContext.KubeAPIContentType, "kube-api-content-type", "", "ContentType used to communicate with apiserver")
@ -126,12 +142,10 @@ func RegisterFlags() {
flag.DurationVar(&TestContext.SystemPodsStartupTimeout, "system-pods-startup-timeout", 10*time.Minute, "Timeout for waiting for all system pods to be running before starting tests.") flag.DurationVar(&TestContext.SystemPodsStartupTimeout, "system-pods-startup-timeout", 10*time.Minute, "Timeout for waiting for all system pods to be running before starting tests.")
flag.StringVar(&TestContext.UpgradeTarget, "upgrade-target", "ci/latest", "Version to upgrade to (e.g. 'release/stable', 'release/latest', 'ci/latest', '0.19.1', '0.19.1-669-gabac8c8') if doing an upgrade test.") flag.StringVar(&TestContext.UpgradeTarget, "upgrade-target", "ci/latest", "Version to upgrade to (e.g. 'release/stable', 'release/latest', 'ci/latest', '0.19.1', '0.19.1-669-gabac8c8') if doing an upgrade test.")
flag.StringVar(&TestContext.PrometheusPushGateway, "prom-push-gateway", "", "The URL to prometheus gateway, so that metrics can be pushed during e2es and scraped by prometheus. Typically something like 127.0.0.1:9091.") flag.StringVar(&TestContext.PrometheusPushGateway, "prom-push-gateway", "", "The URL to prometheus gateway, so that metrics can be pushed during e2es and scraped by prometheus. Typically something like 127.0.0.1:9091.")
flag.BoolVar(&TestContext.VerifyServiceAccount, "e2e-verify-service-account", true, "If true tests will verify the service account before running.")
flag.BoolVar(&TestContext.DeleteNamespace, "delete-namespace", true, "If true tests will delete namespace after completion. It is only designed to make debugging easier, DO NOT turn it off by default.")
flag.BoolVar(&TestContext.CleanStart, "clean-start", false, "If true, purge all namespaces except default and system before running tests. This serves to Cleanup test namespaces from failed/interrupted e2e runs in a long-lived cluster.") flag.BoolVar(&TestContext.CleanStart, "clean-start", false, "If true, purge all namespaces except default and system before running tests. This serves to Cleanup test namespaces from failed/interrupted e2e runs in a long-lived cluster.")
flag.StringVar(&TestContext.GatherKubeSystemResourceUsageData, "gather-resource-usage", "false", "If set to 'true' or 'all' framework will be monitoring resource usage of system all add-ons in (some) e2e tests, if set to 'master' framework will be monitoring master node only, if set to 'none' of 'false' monitoring will be turned off.") }
flag.BoolVar(&TestContext.GatherLogsSizes, "gather-logs-sizes", false, "If set to true framework will be monitoring logs sizes on all machines running e2e tests.")
flag.BoolVar(&TestContext.GatherMetricsAfterTest, "gather-metrics-at-teardown", false, "If set to true framwork will gather metrics from all components after each test.") // Register flags specific to the node e2e test suite.
flag.StringVar(&TestContext.OutputPrintType, "output-print-type", "hr", "Comma separated list: 'hr' for human readable summaries 'json' for JSON ones.") func RegisterNodeFlags() {
flag.BoolVar(&TestContext.DumpLogsOnFailure, "dump-logs-on-failure", true, "If set to true test will dump data about the namespace in which test was running.") flag.StringVar(&TestContext.NodeName, "node-name", "", "Name of the node to run tests on (node e2e suite only).")
} }

View File

@ -121,13 +121,8 @@ var _ = framework.KubeDescribe("ConfigMap", func() {
}, },
} }
assignPodToNode(pod)
By("Creating the pod") By("Creating the pod")
_, err = f.Client.Pods(f.Namespace.Name).Create(pod) f.CreatePod(pod)
Expect(err).NotTo(HaveOccurred())
framework.ExpectNoError(framework.WaitForPodRunningInNamespace(f.Client, pod.Name, f.Namespace.Name))
pollLogs := func() (string, error) { pollLogs := func() (string, error) {
return framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, containerName) 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{ framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{
"CONFIG_DATA_1=value-1", "CONFIG_DATA_1=value-1",
@ -265,7 +260,7 @@ func doConfigMapE2EWithoutMappings(f *framework.Framework, uid, fsGroup int64) {
pod.Spec.SecurityContext.FSGroup = &fsGroup pod.Spec.SecurityContext.FSGroup = &fsGroup
} }
assignPodToNode(pod) f.MungePodSpec(pod)
framework.TestContainerOutput("consume configMaps", f.Client, 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",
@ -338,7 +333,7 @@ func doConfigMapE2EWithMappings(f *framework.Framework, uid, fsGroup int64) {
pod.Spec.SecurityContext.FSGroup = &fsGroup pod.Spec.SecurityContext.FSGroup = &fsGroup
} }
assignPodToNode(pod) f.MungePodSpec(pod)
framework.TestContainerOutput("consume configMaps", f.Client, 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",

View File

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

View File

@ -36,14 +36,11 @@ var _ = framework.KubeDescribe("Kubelet Container Manager", func() {
BeforeEach(func() { BeforeEach(func() {
podName = "bin-false" + string(util.NewUUID()) podName = "bin-false" + string(util.NewUUID())
pod := &api.Pod{ f.CreatePodAsync(&api.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: podName, Name: podName,
Namespace: f.Namespace.Name,
}, },
Spec: api.PodSpec{ 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 // Don't restart the Pod since it is expected to exit
RestartPolicy: api.RestartPolicyNever, RestartPolicy: api.RestartPolicyNever,
Containers: []api.Container{ 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() { It("should have an error terminated reason", func() {
Eventually(func() error { Eventually(func() error {
podData, err := f.Client.Pods(f.Namespace.Name).Get(podName) podData, err := f.PodClient().Get(podName)
if err != nil { if err != nil {
return err return err
} }
@ -81,7 +75,7 @@ var _ = framework.KubeDescribe("Kubelet Container Manager", func() {
}) })
It("should be possible to delete", 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)) 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, RestartPolicy: api.RestartPolicyNever,
}, },
} }
assignPodToNode(pod) f.MungePodSpec(pod)
f.TestContainerOutputRegexp("downward api env vars", pod, 0, expectations) f.TestContainerOutputRegexp("downward api env vars", pod, 0, expectations)
} }

View File

@ -31,6 +31,8 @@ import (
"testing" "testing"
"time" "time"
"k8s.io/kubernetes/test/e2e/framework"
"github.com/golang/glog" "github.com/golang/glog"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
more_reporters "github.com/onsi/ginkgo/reporters" 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 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.") 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) { func TestE2eNode(t *testing.T) {
flag.Parse() flag.Parse()
@ -67,12 +74,12 @@ var _ = BeforeSuite(func() {
if *buildServices { if *buildServices {
buildGo() buildGo()
} }
if *nodeName == "" { if framework.TestContext.NodeName == "" {
output, err := exec.Command("hostname").CombinedOutput() output, err := exec.Command("hostname").CombinedOutput()
if err != nil { if err != nil {
glog.Fatalf("Could not get node name from hostname %v. Output:\n%s", err, output) 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 // 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() maskLocksmithdOnCoreos()
if *startServices { if *startServices {
e2es = newE2eService(*nodeName) e2es = newE2eService(framework.TestContext.NodeName)
if err := e2es.start(); err != nil { if err := e2es.start(); err != nil {
Fail(fmt.Sprintf("Unable to start node services.\n%v", err)) 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() { Context("when scheduling a busybox command in a pod", func() {
podName := "busybox-scheduling-" + string(util.NewUUID()) podName := "busybox-scheduling-" + string(util.NewUUID())
It("it should print the output to logs", func() { It("it should print the output to logs", func() {
podClient := f.Client.Pods(f.Namespace.Name) f.CreatePod(&api.Pod{
pod := &api.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: podName, Name: podName,
}, },
Spec: api.PodSpec{ 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 // Don't restart the Pod since it is expected to exit
RestartPolicy: api.RestartPolicyNever, RestartPolicy: api.RestartPolicyNever,
Containers: []api.Container{ 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 { Eventually(func() string {
sinceTime := apiUnversioned.NewTime(time.Now().Add(time.Duration(-1 * time.Hour))) 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 { if err != nil {
return "" return ""
} }
@ -82,15 +75,12 @@ var _ = framework.KubeDescribe("Kubelet", func() {
Context("when scheduling a read only busybox container", func() { Context("when scheduling a read only busybox container", func() {
podName := "busybox-readonly-fs" + string(util.NewUUID()) podName := "busybox-readonly-fs" + string(util.NewUUID())
It("it should not write to root filesystem", func() { It("it should not write to root filesystem", func() {
podClient := f.Client.Pods(f.Namespace.Name)
isReadOnly := true isReadOnly := true
pod := &api.Pod{ f.CreatePod(&api.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: podName, Name: podName,
}, },
Spec: api.PodSpec{ 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 // Don't restart the Pod since it is expected to exit
RestartPolicy: api.RestartPolicyNever, RestartPolicy: api.RestartPolicyNever,
Containers: []api.Container{ 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 { Eventually(func() string {
rc, err := podClient.GetLogs(podName, &api.PodLogOptions{}).Stream() rc, err := f.PodClient().GetLogs(podName, &api.PodLogOptions{}).Stream()
if err != nil { if err != nil {
return "" return ""
} }
@ -172,46 +159,38 @@ func createSummaryTestPods(f *framework.Framework, podNamePrefix string, count i
podNames.Insert(fmt.Sprintf("%s%v", podNamePrefix, i)) podNames.Insert(fmt.Sprintf("%s%v", podNamePrefix, i))
} }
var pods []*api.Pod
for _, podName := range podNames.List() { for _, podName := range podNames.List() {
createPod(f, podName, []api.Container{ pods = append(pods, &api.Pod{
{ ObjectMeta: api.ObjectMeta{
Image: ImageRegistry[busyBoxImage], Name: podName,
Command: []string{"sh", "-c", "while true; do echo 'hello world' | tee /test-empty-dir-mnt/file ; sleep 1; done"}, },
Name: podName + containerSuffix, Spec: api.PodSpec{
VolumeMounts: []api.VolumeMount{ // Don't restart the Pod since it is expected to exit
{MountPath: "/test-empty-dir-mnt", Name: volumeNamePrefix}, 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 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. // Returns pods missing from summary.
func podsMissingFromSummary(s stats.Summary, expectedPods sets.String) sets.String { func podsMissingFromSummary(s stats.Summary, expectedPods sets.String) sets.String {
expectedPods = sets.StringKeySet(expectedPods) expectedPods = sets.StringKeySet(expectedPods)
@ -244,7 +223,7 @@ func testSummaryMetrics(s stats.Summary, podNamePrefix string) error {
nonNilValue = "expected %q to not be nil" nonNilValue = "expected %q to not be nil"
nonZeroValue = "expected %q to not be zero" 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) return fmt.Errorf("unexpected node name - %q", s.Node.NodeName)
} }
if s.Node.CPU.UsageCoreNanoSeconds == nil { if s.Node.CPU.UsageCoreNanoSeconds == nil {

View File

@ -27,6 +27,7 @@ import (
"k8s.io/kubernetes/pkg/apimachinery/registered" "k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/restclient"
client "k8s.io/kubernetes/pkg/client/unversioned" client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/test/e2e/framework"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "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) { 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 // Manually assign pod to node because we don't run the scheduler in node
// e2e tests. // e2e tests.
assignPodToNode(pod) pod.Spec.NodeName = framework.TestContext.NodeName
createdPod, err := c.Pods(pod.Namespace).Create(pod) createdPod, err := c.Pods(pod.Namespace).Create(pod)
return createdPod, err return createdPod, err
} }

View File

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

View File

@ -19,14 +19,13 @@ package e2e_node
import ( import (
"flag" "flag"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/test/e2e/framework" "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 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 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 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 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") 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, ClientBurst: 100,
}, nil, f) }, nil, f)
} }
func assignPodToNode(pod *api.Pod) {
pod.Spec.NodeName = *nodeName
}