Skip to content

Commit 331fde8

Browse files
author
k8s-merge-robot
authored
Merge pull request kubernetes#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 kubernetes#26228 to go in. Prerequisite for kubernetes#26215
2 parents 9aff7d9 + 376b5f2 commit 331fde8

12 files changed

+166
-119
lines changed

test/e2e/e2e_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import (
2323
)
2424

2525
func init() {
26-
framework.RegisterFlags()
26+
framework.RegisterCommonFlags()
27+
framework.RegisterClusterFlags()
2728
}
2829

2930
func TestE2E(t *testing.T) {

test/e2e/framework/pods.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
Copyright 2016 The Kubernetes Authors All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package framework
18+
19+
import (
20+
"sync"
21+
22+
"k8s.io/kubernetes/pkg/api"
23+
"k8s.io/kubernetes/pkg/client/unversioned"
24+
25+
. "github.com/onsi/gomega"
26+
)
27+
28+
// TODO: Consolidate pod-specific framework functions here.
29+
30+
// Convenience method for getting a pod client interface in the framework's namespace.
31+
func (f *Framework) PodClient() unversioned.PodInterface {
32+
return f.Client.Pods(f.Namespace.Name)
33+
}
34+
35+
// Create a new pod according to the framework specifications, and wait for it to start.
36+
func (f *Framework) CreatePod(pod *api.Pod) {
37+
f.CreatePodAsync(pod)
38+
ExpectNoError(f.WaitForPodRunning(pod.Name))
39+
}
40+
41+
// Create a new pod according to the framework specifications (don't wait for it to start).
42+
func (f *Framework) CreatePodAsync(pod *api.Pod) {
43+
f.MungePodSpec(pod)
44+
_, err := f.PodClient().Create(pod)
45+
ExpectNoError(err, "Error creating Pod")
46+
}
47+
48+
// Batch version of CreatePod. All pods are created before waiting.
49+
func (f *Framework) CreatePods(pods []*api.Pod) {
50+
for _, pod := range pods {
51+
f.CreatePodAsync(pod)
52+
}
53+
var wg sync.WaitGroup
54+
for _, pod := range pods {
55+
wg.Add(1)
56+
podName := pod.Name
57+
go func() {
58+
ExpectNoError(f.WaitForPodRunning(podName))
59+
wg.Done()
60+
}()
61+
}
62+
wg.Wait()
63+
}
64+
65+
// Apply test-suite specific transformations to the pod spec.
66+
// TODO: figure out a nicer, more generic way to tie this to framework instances.
67+
func (f *Framework) MungePodSpec(pod *api.Pod) {
68+
if TestContext.NodeName != "" {
69+
Expect(pod.Spec.NodeName).To(Or(BeZero(), Equal(TestContext.NodeName)), "Test misconfigured")
70+
pod.Spec.NodeName = TestContext.NodeName
71+
}
72+
}

test/e2e/framework/test_context.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ type TestContextType struct {
6565
CreateTestingNS CreateTestingNSFn
6666
// If set to true test will dump data about the namespace in which test was running.
6767
DumpLogsOnFailure bool
68+
// Name of the node to run tests on (node e2e suite only).
69+
NodeName string
6870
}
6971

7072
type CloudConfig struct {
@@ -83,7 +85,8 @@ type CloudConfig struct {
8385
var TestContext TestContextType
8486
var federatedKubeContext string
8587

86-
func RegisterFlags() {
88+
// Register flags common to all e2e test suites.
89+
func RegisterCommonFlags() {
8790
// Turn on verbose by default to get spec names
8891
config.DefaultReporterConfig.Verbose = true
8992

@@ -93,6 +96,19 @@ func RegisterFlags() {
9396
// Randomize specs as well as suites
9497
config.GinkgoConfig.RandomizeAllSpecs = true
9598

99+
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.")
100+
flag.BoolVar(&TestContext.GatherLogsSizes, "gather-logs-sizes", false, "If set to true framework will be monitoring logs sizes on all machines running e2e tests.")
101+
flag.BoolVar(&TestContext.GatherMetricsAfterTest, "gather-metrics-at-teardown", false, "If set to true framwork will gather metrics from all components after each test.")
102+
flag.StringVar(&TestContext.OutputPrintType, "output-print-type", "hr", "Comma separated list: 'hr' for human readable summaries 'json' for JSON ones.")
103+
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.")
104+
}
105+
106+
// Register flags specific to the cluster e2e test suite.
107+
func RegisterClusterFlags() {
108+
// TODO: Move to common flags once namespace deletion is fixed for node e2e.
109+
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.")
110+
111+
flag.BoolVar(&TestContext.VerifyServiceAccount, "e2e-verify-service-account", true, "If true tests will verify the service account before running.")
96112
flag.StringVar(&TestContext.KubeConfig, clientcmd.RecommendedConfigPathFlag, os.Getenv(clientcmd.RecommendedConfigPathEnvVar), "Path to kubeconfig containing embedded authinfo.")
97113
flag.StringVar(&TestContext.KubeContext, clientcmd.FlagContext, "", "kubeconfig context to use/override. If unset, will use value from 'current-context'")
98114
flag.StringVar(&TestContext.KubeAPIContentType, "kube-api-content-type", "", "ContentType used to communicate with apiserver")
@@ -126,12 +142,10 @@ func RegisterFlags() {
126142
flag.DurationVar(&TestContext.SystemPodsStartupTimeout, "system-pods-startup-timeout", 10*time.Minute, "Timeout for waiting for all system pods to be running before starting tests.")
127143
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.")
128144
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.")
129-
flag.BoolVar(&TestContext.VerifyServiceAccount, "e2e-verify-service-account", true, "If true tests will verify the service account before running.")
130-
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.")
131145
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.")
132-
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.")
133-
flag.BoolVar(&TestContext.GatherLogsSizes, "gather-logs-sizes", false, "If set to true framework will be monitoring logs sizes on all machines running e2e tests.")
134-
flag.BoolVar(&TestContext.GatherMetricsAfterTest, "gather-metrics-at-teardown", false, "If set to true framwork will gather metrics from all components after each test.")
135-
flag.StringVar(&TestContext.OutputPrintType, "output-print-type", "hr", "Comma separated list: 'hr' for human readable summaries 'json' for JSON ones.")
136-
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.")
146+
}
147+
148+
// Register flags specific to the node e2e test suite.
149+
func RegisterNodeFlags() {
150+
flag.StringVar(&TestContext.NodeName, "node-name", "", "Name of the node to run tests on (node e2e suite only).")
137151
}

test/e2e_node/configmap.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,8 @@ var _ = framework.KubeDescribe("ConfigMap", func() {
121121
},
122122
}
123123

124-
assignPodToNode(pod)
125-
126124
By("Creating the pod")
127-
_, err = f.Client.Pods(f.Namespace.Name).Create(pod)
128-
Expect(err).NotTo(HaveOccurred())
129-
130-
framework.ExpectNoError(framework.WaitForPodRunningInNamespace(f.Client, pod.Name, f.Namespace.Name))
125+
f.CreatePod(pod)
131126

132127
pollLogs := func() (string, error) {
133128
return framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, containerName)
@@ -184,7 +179,7 @@ var _ = framework.KubeDescribe("ConfigMap", func() {
184179
},
185180
}
186181

187-
assignPodToNode(pod)
182+
f.MungePodSpec(pod)
188183

189184
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{
190185
"CONFIG_DATA_1=value-1",
@@ -265,7 +260,7 @@ func doConfigMapE2EWithoutMappings(f *framework.Framework, uid, fsGroup int64) {
265260
pod.Spec.SecurityContext.FSGroup = &fsGroup
266261
}
267262

268-
assignPodToNode(pod)
263+
f.MungePodSpec(pod)
269264

270265
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{
271266
"content of file \"/etc/configmap-volume/data-1\": value-1",
@@ -338,7 +333,7 @@ func doConfigMapE2EWithMappings(f *framework.Framework, uid, fsGroup int64) {
338333
pod.Spec.SecurityContext.FSGroup = &fsGroup
339334
}
340335

341-
assignPodToNode(pod)
336+
f.MungePodSpec(pod)
342337

343338
framework.TestContainerOutput("consume configMaps", f.Client, pod, 0, []string{
344339
"content of file \"/etc/configmap-volume/path/to/data-2\": value-2",

test/e2e_node/container.go

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,33 @@ import (
2121

2222
"k8s.io/kubernetes/pkg/api"
2323
"k8s.io/kubernetes/pkg/api/errors"
24-
client "k8s.io/kubernetes/pkg/client/unversioned"
2524
"k8s.io/kubernetes/pkg/util"
25+
"k8s.io/kubernetes/test/e2e/framework"
2626
)
2727

2828
// One pod one container
29+
// TODO: This should be migrated to the e2e framework.
2930
type ConformanceContainer struct {
31+
Framework *framework.Framework
3032
Container api.Container
31-
Client *client.Client
3233
RestartPolicy api.RestartPolicy
3334
Volumes []api.Volume
3435
ImagePullSecrets []string
35-
NodeName string
36-
Namespace string
3736

3837
podName string
3938
}
4039

41-
func (cc *ConformanceContainer) Create() error {
40+
func (cc *ConformanceContainer) Create() {
4241
cc.podName = cc.Container.Name + string(util.NewUUID())
4342
imagePullSecrets := []api.LocalObjectReference{}
4443
for _, s := range cc.ImagePullSecrets {
4544
imagePullSecrets = append(imagePullSecrets, api.LocalObjectReference{Name: s})
4645
}
4746
pod := &api.Pod{
4847
ObjectMeta: api.ObjectMeta{
49-
Name: cc.podName,
50-
Namespace: cc.Namespace,
48+
Name: cc.podName,
5149
},
5250
Spec: api.PodSpec{
53-
NodeName: cc.NodeName,
5451
RestartPolicy: cc.RestartPolicy,
5552
Containers: []api.Container{
5653
cc.Container,
@@ -59,33 +56,31 @@ func (cc *ConformanceContainer) Create() error {
5956
ImagePullSecrets: imagePullSecrets,
6057
},
6158
}
62-
63-
_, err := cc.Client.Pods(cc.Namespace).Create(pod)
64-
return err
59+
cc.Framework.CreatePodAsync(pod)
6560
}
6661

6762
func (cc *ConformanceContainer) Delete() error {
68-
return cc.Client.Pods(cc.Namespace).Delete(cc.podName, api.NewDeleteOptions(0))
63+
return cc.Framework.PodClient().Delete(cc.podName, api.NewDeleteOptions(0))
6964
}
7065

7166
func (cc *ConformanceContainer) IsReady() (bool, error) {
72-
pod, err := cc.Client.Pods(cc.Namespace).Get(cc.podName)
67+
pod, err := cc.Framework.PodClient().Get(cc.podName)
7368
if err != nil {
7469
return false, err
7570
}
7671
return api.IsPodReady(pod), nil
7772
}
7873

7974
func (cc *ConformanceContainer) GetPhase() (api.PodPhase, error) {
80-
pod, err := cc.Client.Pods(cc.Namespace).Get(cc.podName)
75+
pod, err := cc.Framework.PodClient().Get(cc.podName)
8176
if err != nil {
8277
return api.PodUnknown, err
8378
}
8479
return pod.Status.Phase, nil
8580
}
8681

8782
func (cc *ConformanceContainer) GetStatus() (api.ContainerStatus, error) {
88-
pod, err := cc.Client.Pods(cc.Namespace).Get(cc.podName)
83+
pod, err := cc.Framework.PodClient().Get(cc.podName)
8984
if err != nil {
9085
return api.ContainerStatus{}, err
9186
}
@@ -97,7 +92,7 @@ func (cc *ConformanceContainer) GetStatus() (api.ContainerStatus, error) {
9792
}
9893

9994
func (cc *ConformanceContainer) Present() (bool, error) {
100-
_, err := cc.Client.Pods(cc.Namespace).Get(cc.podName)
95+
_, err := cc.Framework.PodClient().Get(cc.podName)
10196
if err == nil {
10297
return true, nil
10398
}

test/e2e_node/container_manager_test.go

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,11 @@ var _ = framework.KubeDescribe("Kubelet Container Manager", func() {
3636

3737
BeforeEach(func() {
3838
podName = "bin-false" + string(util.NewUUID())
39-
pod := &api.Pod{
39+
f.CreatePodAsync(&api.Pod{
4040
ObjectMeta: api.ObjectMeta{
41-
Name: podName,
42-
Namespace: f.Namespace.Name,
41+
Name: podName,
4342
},
4443
Spec: api.PodSpec{
45-
// Force the Pod to schedule to the node without a scheduler running
46-
NodeName: *nodeName,
4744
// Don't restart the Pod since it is expected to exit
4845
RestartPolicy: api.RestartPolicyNever,
4946
Containers: []api.Container{
@@ -54,15 +51,12 @@ var _ = framework.KubeDescribe("Kubelet Container Manager", func() {
5451
},
5552
},
5653
},
57-
}
58-
59-
_, err := f.Client.Pods(f.Namespace.Name).Create(pod)
60-
Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err))
54+
})
6155
})
6256

6357
It("should have an error terminated reason", func() {
6458
Eventually(func() error {
65-
podData, err := f.Client.Pods(f.Namespace.Name).Get(podName)
59+
podData, err := f.PodClient().Get(podName)
6660
if err != nil {
6761
return err
6862
}
@@ -81,7 +75,7 @@ var _ = framework.KubeDescribe("Kubelet Container Manager", func() {
8175
})
8276

8377
It("should be possible to delete", func() {
84-
err := f.Client.Pods(f.Namespace.Name).Delete(podName, &api.DeleteOptions{})
78+
err := f.PodClient().Delete(podName, &api.DeleteOptions{})
8579
Expect(err).To(BeNil(), fmt.Sprintf("Error deleting Pod %v", err))
8680
})
8781
})

test/e2e_node/downward_api_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func testDownwardAPI(f *framework.Framework, podName string, env []api.EnvVar, e
158158
RestartPolicy: api.RestartPolicyNever,
159159
},
160160
}
161-
assignPodToNode(pod)
161+
f.MungePodSpec(pod)
162162

163163
f.TestContainerOutputRegexp("downward api env vars", pod, 0, expectations)
164164
}

test/e2e_node/e2e_node_suite_test.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import (
3131
"testing"
3232
"time"
3333

34+
"k8s.io/kubernetes/test/e2e/framework"
35+
3436
"github.com/golang/glog"
3537
. "github.com/onsi/ginkgo"
3638
more_reporters "github.com/onsi/ginkgo/reporters"
@@ -42,6 +44,11 @@ var e2es *e2eService
4244
var prePullImages = flag.Bool("prepull-images", true, "If true, prepull images so image pull failures do not cause test failures.")
4345
var junitFileNumber = flag.Int("junit-file-number", 1, "Used to create junit filename - e.g. junit_01.xml.")
4446

47+
func init() {
48+
framework.RegisterCommonFlags()
49+
framework.RegisterNodeFlags()
50+
}
51+
4552
func TestE2eNode(t *testing.T) {
4653
flag.Parse()
4754

@@ -67,12 +74,12 @@ var _ = BeforeSuite(func() {
6774
if *buildServices {
6875
buildGo()
6976
}
70-
if *nodeName == "" {
77+
if framework.TestContext.NodeName == "" {
7178
output, err := exec.Command("hostname").CombinedOutput()
7279
if err != nil {
7380
glog.Fatalf("Could not get node name from hostname %v. Output:\n%s", err, output)
7481
}
75-
*nodeName = strings.TrimSpace(fmt.Sprintf("%s", output))
82+
framework.TestContext.NodeName = strings.TrimSpace(fmt.Sprintf("%s", output))
7683
}
7784

7885
// 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() {
8996
maskLocksmithdOnCoreos()
9097

9198
if *startServices {
92-
e2es = newE2eService(*nodeName)
99+
e2es = newE2eService(framework.TestContext.NodeName)
93100
if err := e2es.start(); err != nil {
94101
Fail(fmt.Sprintf("Unable to start node services.\n%v", err))
95102
}

0 commit comments

Comments
 (0)