diff --git a/test/e2e/framework/BUILD b/test/e2e/framework/BUILD index c2a8d33744d..0957a2c3ca6 100644 --- a/test/e2e/framework/BUILD +++ b/test/e2e/framework/BUILD @@ -43,7 +43,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library", diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index e574a8ee3b9..048c50d5ee9 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -38,7 +38,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/discovery" cacheddiscovery "k8s.io/client-go/discovery/cached/memory" @@ -48,14 +47,12 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/restmapper" scaleclient "k8s.io/client-go/scale" - testutils "k8s.io/kubernetes/test/utils" "github.com/onsi/ginkgo" "github.com/onsi/gomega" // TODO: Remove the following imports (ref: https://github.com/kubernetes/kubernetes/issues/81245) e2emetrics "k8s.io/kubernetes/test/e2e/framework/metrics" - e2enode "k8s.io/kubernetes/test/e2e/framework/node" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" ) @@ -568,76 +565,6 @@ func (f *Framework) TestContainerOutputRegexp(scenarioName string, pod *v1.Pod, f.testContainerOutputMatcher(scenarioName, pod, containerIndex, expectedOutput, gomega.MatchRegexp) } -// CreateServiceForSimpleAppWithPods is a convenience wrapper to create a service and its matching pods all at once. -func (f *Framework) CreateServiceForSimpleAppWithPods(contPort int, svcPort int, appName string, podSpec func(n v1.Node) v1.PodSpec, count int, block bool) (*v1.Service, error) { - var err error - theService := f.CreateServiceForSimpleApp(contPort, svcPort, appName) - f.CreatePodsPerNodeForSimpleApp(appName, podSpec, count) - if block { - err = testutils.WaitForPodsWithLabelRunning(f.ClientSet, f.Namespace.Name, labels.SelectorFromSet(labels.Set(theService.Spec.Selector))) - } - return theService, err -} - -// CreateServiceForSimpleApp returns a service that selects/exposes pods (send -1 ports if no exposure needed) with an app label. -func (f *Framework) CreateServiceForSimpleApp(contPort, svcPort int, appName string) *v1.Service { - if appName == "" { - panic(fmt.Sprintf("no app name provided")) - } - - serviceSelector := map[string]string{ - "app": appName + "-pod", - } - - // For convenience, user sending ports are optional. - portsFunc := func() []v1.ServicePort { - if contPort < 1 || svcPort < 1 { - return nil - } - return []v1.ServicePort{{ - Protocol: v1.ProtocolTCP, - Port: int32(svcPort), - TargetPort: intstr.FromInt(contPort), - }} - } - Logf("Creating a service-for-%v for selecting app=%v-pod", appName, appName) - service, err := f.ClientSet.CoreV1().Services(f.Namespace.Name).Create(context.TODO(), &v1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: "service-for-" + appName, - Labels: map[string]string{ - "app": appName + "-service", - }, - }, - Spec: v1.ServiceSpec{ - Ports: portsFunc(), - Selector: serviceSelector, - }, - }, metav1.CreateOptions{}) - ExpectNoError(err) - return service -} - -// CreatePodsPerNodeForSimpleApp creates pods w/ labels. Useful for tests which make a bunch of pods w/o any networking. -func (f *Framework) CreatePodsPerNodeForSimpleApp(appName string, podSpec func(n v1.Node) v1.PodSpec, maxCount int) map[string]string { - nodes, err := e2enode.GetBoundedReadySchedulableNodes(f.ClientSet, maxCount) - ExpectNoError(err) - podLabels := map[string]string{ - "app": appName + "-pod", - } - for i, node := range nodes.Items { - Logf("%v/%v : Creating container with label app=%v-pod", i, maxCount, appName) - _, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(context.TODO(), &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(appName+"-pod-%v", i), - Labels: podLabels, - }, - Spec: podSpec(node), - }, metav1.CreateOptions{}) - ExpectNoError(err) - } - return podLabels -} - // KubeUser is a struct for managing kubernetes user info. type KubeUser struct { Name string `yaml:"name"` diff --git a/test/e2e/framework/node/BUILD b/test/e2e/framework/node/BUILD index fe860e6d64e..be8e918dda3 100644 --- a/test/e2e/framework/node/BUILD +++ b/test/e2e/framework/node/BUILD @@ -23,6 +23,7 @@ go_library( "//test/e2e/system:go_default_library", "//test/utils:go_default_library", "//test/utils/image:go_default_library", + "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", ], ) diff --git a/test/e2e/framework/node/resource.go b/test/e2e/framework/node/resource.go index 21965f12280..1b1b313f84f 100644 --- a/test/e2e/framework/node/resource.go +++ b/test/e2e/framework/node/resource.go @@ -23,6 +23,8 @@ import ( "strings" "time" + "github.com/onsi/gomega" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" @@ -516,3 +518,26 @@ func GetClusterZones(c clientset.Interface) (sets.String, error) { } return zones, nil } + +// CreatePodsPerNodeForSimpleApp creates pods w/ labels. Useful for tests which make a bunch of pods w/o any networking. +func CreatePodsPerNodeForSimpleApp(c clientset.Interface, namespace, appName string, podSpec func(n v1.Node) v1.PodSpec, maxCount int) map[string]string { + nodes, err := GetBoundedReadySchedulableNodes(c, maxCount) + // TODO use wrapper methods in expect.go after removing core e2e dependency on node + gomega.ExpectWithOffset(2, err).NotTo(gomega.HaveOccurred()) + podLabels := map[string]string{ + "app": appName + "-pod", + } + for i, node := range nodes.Items { + e2elog.Logf("%v/%v : Creating container with label app=%v-pod", i, maxCount, appName) + _, err := c.CoreV1().Pods(namespace).Create(context.TODO(), &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf(appName+"-pod-%v", i), + Labels: podLabels, + }, + Spec: podSpec(node), + }, metav1.CreateOptions{}) + // TODO use wrapper methods in expect.go after removing core e2e dependency on node + gomega.ExpectWithOffset(2, err).NotTo(gomega.HaveOccurred()) + } + return podLabels +} diff --git a/test/e2e/framework/service/resource.go b/test/e2e/framework/service/resource.go index 91fd3d4c99c..88cb0335d34 100644 --- a/test/e2e/framework/service/resource.go +++ b/test/e2e/framework/service/resource.go @@ -18,15 +18,19 @@ package service import ( "context" + "fmt" "time" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/util/intstr" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/kubernetes/test/e2e/framework" e2enode "k8s.io/kubernetes/test/e2e/framework/node" + testutils "k8s.io/kubernetes/test/utils" ) // GetServicesProxyRequest returns a request for a service proxy. @@ -104,3 +108,52 @@ func GetServiceLoadBalancerCreationTimeout(cs clientset.Interface) time.Duration } return LoadBalancerCreateTimeoutDefault } + +// CreateServiceForSimpleAppWithPods is a convenience wrapper to create a service and its matching pods all at once. +func CreateServiceForSimpleAppWithPods(c clientset.Interface, contPort int, svcPort int, namespace, appName string, podSpec func(n v1.Node) v1.PodSpec, count int, block bool) (*v1.Service, error) { + var err error + theService := CreateServiceForSimpleApp(c, contPort, svcPort, namespace, appName) + e2enode.CreatePodsPerNodeForSimpleApp(c, namespace, appName, podSpec, count) + if block { + err = testutils.WaitForPodsWithLabelRunning(c, namespace, labels.SelectorFromSet(labels.Set(theService.Spec.Selector))) + } + return theService, err +} + +// CreateServiceForSimpleApp returns a service that selects/exposes pods (send -1 ports if no exposure needed) with an app label. +func CreateServiceForSimpleApp(c clientset.Interface, contPort, svcPort int, namespace, appName string) *v1.Service { + if appName == "" { + panic(fmt.Sprintf("no app name provided")) + } + + serviceSelector := map[string]string{ + "app": appName + "-pod", + } + + // For convenience, user sending ports are optional. + portsFunc := func() []v1.ServicePort { + if contPort < 1 || svcPort < 1 { + return nil + } + return []v1.ServicePort{{ + Protocol: v1.ProtocolTCP, + Port: int32(svcPort), + TargetPort: intstr.FromInt(contPort), + }} + } + framework.Logf("Creating a service-for-%v for selecting app=%v-pod", appName, appName) + service, err := c.CoreV1().Services(namespace).Create(context.TODO(), &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "service-for-" + appName, + Labels: map[string]string{ + "app": appName + "-service", + }, + }, + Spec: v1.ServiceSpec{ + Ports: portsFunc(), + Selector: serviceSelector, + }, + }, metav1.CreateOptions{}) + framework.ExpectNoError(err) + return service +} diff --git a/test/e2e/instrumentation/logging/generic_soak.go b/test/e2e/instrumentation/logging/generic_soak.go index 075788fcd4a..501a7e21ac8 100644 --- a/test/e2e/instrumentation/logging/generic_soak.go +++ b/test/e2e/instrumentation/logging/generic_soak.go @@ -86,7 +86,9 @@ func RunLogPodsWithSleepOf(f *framework.Framework, sleep time.Duration, podname kilobyte := strings.Repeat("logs-123", 128) // 8*128=1024 = 1KB of text. appName := "logging-soak" + podname - podlables := f.CreatePodsPerNodeForSimpleApp( + podlables := e2enode.CreatePodsPerNodeForSimpleApp( + f.ClientSet, + f.Namespace.Name, appName, func(n v1.Node) v1.PodSpec { return v1.PodSpec{ diff --git a/test/e2e/network/networking_perf.go b/test/e2e/network/networking_perf.go index 26c375cada2..d21b051e300 100644 --- a/test/e2e/network/networking_perf.go +++ b/test/e2e/network/networking_perf.go @@ -25,6 +25,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/kubernetes/test/e2e/framework" e2enode "k8s.io/kubernetes/test/e2e/framework/node" + e2eservice "k8s.io/kubernetes/test/e2e/framework/service" e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" imageutils "k8s.io/kubernetes/test/utils/image" ) @@ -60,9 +61,11 @@ func networkingIPerfTest(isIPv6 bool) { // for a single service, we expect to divide bandwidth between the network. Very crude estimate. expectedBandwidth := int(float64(maxBandwidthBits) / float64(totalPods)) appName := "iperf-e2e" - _, err = f.CreateServiceForSimpleAppWithPods( + _, err = e2eservice.CreateServiceForSimpleAppWithPods( + f.ClientSet, 8001, 8002, + f.Namespace.Name, appName, func(n v1.Node) v1.PodSpec { return v1.PodSpec{ @@ -89,7 +92,9 @@ func networkingIPerfTest(isIPv6 bool) { framework.Failf("Fatal error waiting for iperf server endpoint : %v", err) } - iperfClientPodLabels := f.CreatePodsPerNodeForSimpleApp( + iperfClientPodLabels := e2enode.CreatePodsPerNodeForSimpleApp( + f.ClientSet, + f.Namespace.Name, "iperf-e2e-cli", func(n v1.Node) v1.PodSpec { return v1.PodSpec{