Add e2e multiple endpoint services test

- ensures that when multiple services with the same selector will
 function even if one of the services is deleted
This commit is contained in:
Swetha Repakula 2020-08-25 11:27:42 -07:00
parent a28a692917
commit e6428ae214
3 changed files with 78 additions and 3 deletions

View File

@ -611,11 +611,11 @@ func (config *NetworkingTestConfig) createNodePortServiceSpec(svcName string, se
}
func (config *NetworkingTestConfig) createNodePortService(selector map[string]string) {
config.NodePortService = config.createService(config.createNodePortServiceSpec(nodePortServiceName, selector, false))
config.NodePortService = config.CreateService(config.createNodePortServiceSpec(nodePortServiceName, selector, false))
}
func (config *NetworkingTestConfig) createSessionAffinityService(selector map[string]string) {
config.SessionAffinityService = config.createService(config.createNodePortServiceSpec(sessionAffinityServiceName, selector, true))
config.SessionAffinityService = config.CreateService(config.createNodePortServiceSpec(sessionAffinityServiceName, selector, true))
}
// DeleteNodePortService deletes NodePort service.
@ -651,7 +651,8 @@ func (config *NetworkingTestConfig) createTestPods() {
}
}
func (config *NetworkingTestConfig) createService(serviceSpec *v1.Service) *v1.Service {
// CreateService creates the provided service in config.Namespace and returns created service
func (config *NetworkingTestConfig) CreateService(serviceSpec *v1.Service) *v1.Service {
_, err := config.getServiceClient().Create(context.TODO(), serviceSpec, metav1.CreateOptions{})
framework.ExpectNoError(err, fmt.Sprintf("Failed to create %s service: %v", serviceSpec.Name, err))

View File

@ -226,6 +226,38 @@ var _ = SIGDescribe("Networking", func() {
config.DialFromEndpointContainer("udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
})
// This test ensures that in a situation where multiple services exist with the same selector,
// deleting one of the services does not affect the connectivity of the remaining service
ginkgo.It("should function for multiple endpoint-Services with same selector", func() {
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
ginkgo.By("creating a second service with same selector")
svc2, httpPort := createSecondNodePortService(f, config)
// original service should work
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (config.clusterIP)", config.EndpointPods[0].Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
config.DialFromEndpointContainer("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, config.NodeHTTPPort))
config.DialFromEndpointContainer("http", config.NodeIP, config.NodeHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
// Dial second service
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (svc2.clusterIP)", config.EndpointPods[0].Name, svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort))
config.DialFromEndpointContainer("http", svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, httpPort))
config.DialFromEndpointContainer("http", config.NodeIP, httpPort, config.MaxTries, 0, config.EndpointHostnames())
ginkgo.By("deleting the original node port service")
config.DeleteNodePortService()
// Second service should continue to function unaffected
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (svc2.clusterIP)", config.EndpointPods[0].Name, svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort))
config.DialFromEndpointContainer("http", svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, httpPort))
config.DialFromEndpointContainer("http", config.NodeIP, httpPort, config.MaxTries, 0, config.EndpointHostnames())
})
ginkgo.It("should update endpoints: http", func() {
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))

View File

@ -26,6 +26,7 @@ import (
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/kubernetes/test/e2e/framework"
e2enetwork "k8s.io/kubernetes/test/e2e/framework/network"
@ -33,6 +34,9 @@ import (
imageutils "k8s.io/kubernetes/test/utils/image"
)
// secondNodePortSvcName is the name of the secondary node port service
const secondNodePortSvcName = "second-node-port-service"
var (
// agnHostImage is the image URI of AgnHost
agnHostImage = imageutils.GetE2EImage(imageutils.Agnhost)
@ -162,3 +166,41 @@ func execSourceIPTest(sourcePod v1.Pod, targetAddr string) (string, string) {
}
return sourcePod.Status.PodIP, host
}
// createSecondNodePortService creates a service with the same selector as config.NodePortService and same HTTP Port
func createSecondNodePortService(f *framework.Framework, config *e2enetwork.NetworkingTestConfig) (*v1.Service, int) {
svc := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: secondNodePortSvcName,
},
Spec: v1.ServiceSpec{
Type: v1.ServiceTypeNodePort,
Ports: []v1.ServicePort{
{
Port: e2enetwork.ClusterHTTPPort,
Name: "http",
Protocol: v1.ProtocolTCP,
TargetPort: intstr.FromInt(e2enetwork.EndpointHTTPPort),
},
},
Selector: config.NodePortService.Spec.Selector,
},
}
createdService := config.CreateService(svc)
err := framework.WaitForServiceEndpointsNum(f.ClientSet, config.Namespace, secondNodePortSvcName, len(config.EndpointPods), time.Second, wait.ForeverTestTimeout)
framework.ExpectNoError(err, "failed to validate endpoints for service %s in namespace: %s", secondNodePortSvcName, config.Namespace)
var httpPort int
for _, p := range createdService.Spec.Ports {
switch p.Protocol {
case v1.ProtocolTCP:
httpPort = int(p.NodePort)
default:
continue
}
}
return createdService, httpPort
}