From 3086480a2e02faea27aae50b97edd6d431fc9a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnaud=20Jardin=C3=A9?= Date: Wed, 27 Mar 2019 21:19:46 +0100 Subject: [PATCH 1/2] Add port name to service struct used in minikube service --- pkg/minikube/service/service.go | 43 +++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/pkg/minikube/service/service.go b/pkg/minikube/service/service.go index 0db95eca038d..b68b527b6124 100644 --- a/pkg/minikube/service/service.go +++ b/pkg/minikube/service/service.go @@ -170,29 +170,36 @@ func printURLsForService(c corev1.CoreV1Interface, ip, service, namespace string if err != nil { return nil, errors.Wrapf(err, "service '%s' could not be found running", service) } - var nodePorts []int32 - if len(svc.Spec.Ports) > 0 { - for _, port := range svc.Spec.Ports { - if port.NodePort > 0 { - nodePorts = append(nodePorts, port.NodePort) + + e := c.Endpoints(namespace) + endpoints, err := e.Get(service, metav1.GetOptions{}) + m := make(map[int32]string) + if endpoints != nil && len(endpoints.Subsets) > 0 { + for _, ept := range endpoints.Subsets { + for _, p := range ept.Ports { + m[int32(p.Port)] = p.Name } } } + urls := []string{} - for _, port := range nodePorts { - var doc bytes.Buffer - err = t.Execute(&doc, struct { - IP string - Port int32 - }{ - ip, - port, - }) - if err != nil { - return nil, err + for _, port := range svc.Spec.Ports { + if port.NodePort > 0 { + var doc bytes.Buffer + err = t.Execute(&doc, struct { + IP string + Port int32 + Name string + }{ + ip, + port.NodePort, + m[port.TargetPort.IntVal], + }) + if err != nil { + return nil, err + } + urls = append(urls, doc.String()) } - - urls = append(urls, doc.String()) } return urls, nil } From c57deb5ee5abb64b4398af0b7b2dbd68f2f28aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnaud=20Jardin=C3=A9?= Date: Thu, 28 Mar 2019 18:34:06 +0100 Subject: [PATCH 2/2] Add test --- pkg/minikube/service/service_test.go | 64 ++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/pkg/minikube/service/service_test.go b/pkg/minikube/service/service_test.go index 0a6ed09b4d5f..3656fdd1cf7a 100644 --- a/pkg/minikube/service/service_test.go +++ b/pkg/minikube/service/service_test.go @@ -27,6 +27,7 @@ import ( "github.com/pkg/errors" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" corev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/kubernetes/typed/core/v1/fake" @@ -36,12 +37,14 @@ import ( ) type MockClientGetter struct { - servicesMap map[string]corev1.ServiceInterface + servicesMap map[string]corev1.ServiceInterface + endpointsMap map[string]corev1.EndpointsInterface } func (m *MockClientGetter) GetCoreClient() (corev1.CoreV1Interface, error) { return &MockCoreClient{ - servicesMap: m.servicesMap, + servicesMap: m.servicesMap, + endpointsMap: m.endpointsMap, }, nil } @@ -51,7 +54,8 @@ func (m *MockClientGetter) GetClientset(timeout time.Duration) (*kubernetes.Clie type MockCoreClient struct { fake.FakeCoreV1 - servicesMap map[string]corev1.ServiceInterface + servicesMap map[string]corev1.ServiceInterface + endpointsMap map[string]corev1.EndpointsInterface } var serviceNamespaces = map[string]corev1.ServiceInterface{ @@ -68,8 +72,18 @@ var defaultNamespaceServiceInterface = &MockServiceInterface{ }, Spec: v1.ServiceSpec{ Ports: []v1.ServicePort{ - {NodePort: int32(1111)}, - {NodePort: int32(2222)}, + { + NodePort: int32(1111), + TargetPort: intstr.IntOrString{ + IntVal: int32(11111), + }, + }, + { + NodePort: int32(2222), + TargetPort: intstr.IntOrString{ + IntVal: int32(22222), + }, + }, }, }, }, @@ -86,8 +100,14 @@ var defaultNamespaceServiceInterface = &MockServiceInterface{ }, } +var endpointNamespaces = map[string]corev1.EndpointsInterface{ + "default": defaultNamespaceEndpointInterface, +} + +var defaultNamespaceEndpointInterface = &MockEndpointsInterface{} + func (m *MockCoreClient) Endpoints(namespace string) corev1.EndpointsInterface { - return &MockEndpointsInterface{} + return m.endpointsMap[namespace] } func (m *MockCoreClient) Services(namespace string) corev1.ServiceInterface { @@ -124,6 +144,22 @@ var endpointMap = map[string]*v1.Endpoints{ }, }, }, + "mock-dashboard": { + Subsets: []v1.EndpointSubset{ + { + Ports: []v1.EndpointPort{ + { + Name: "port1", + Port: int32(11111), + }, + { + Name: "port2", + Port: int32(22222), + }, + }, + }, + }, + }, } func (e MockEndpointsInterface) Get(name string, _ metav1.GetOptions) (*v1.Endpoints, error) { @@ -195,7 +231,8 @@ func TestGetServiceListFromServicesByLabel(t *testing.T) { func TestPrintURLsForService(t *testing.T) { defaultTemplate := template.Must(template.New("svc-template").Parse("http://{{.IP}}:{{.Port}}")) client := &MockCoreClient{ - servicesMap: serviceNamespaces, + servicesMap: serviceNamespaces, + endpointsMap: endpointNamespaces, } var tests = []struct { description string @@ -219,6 +256,13 @@ func TestPrintURLsForService(t *testing.T) { tmpl: template.Must(template.New("svc-arbitrary-template").Parse("{{.IP}}:{{.Port}}")), expectedOutput: []string{"127.0.0.1:1111", "127.0.0.1:2222"}, }, + { + description: "should get the name of all target ports with arbitrary format", + serviceName: "mock-dashboard", + namespace: "default", + tmpl: template.Must(template.New("svc-arbitrary-template").Parse("{{.Name}}={{.IP}}:{{.Port}}")), + expectedOutput: []string{"port1=127.0.0.1:1111", "port2=127.0.0.1:2222"}, + }, { description: "empty slice for no node ports", serviceName: "mock-dashboard-no-ports", @@ -361,7 +405,8 @@ func TestGetServiceURLs(t *testing.T) { t.Parallel() K8s = &MockClientGetter{ - servicesMap: serviceNamespaces, + servicesMap: serviceNamespaces, + endpointsMap: endpointNamespaces, } urls, err := GetServiceURLs(test.api, test.namespace, defaultTemplate) if err != nil && !test.err { @@ -428,7 +473,8 @@ func TestGetServiceURLsForService(t *testing.T) { t.Run(test.description, func(t *testing.T) { t.Parallel() K8s = &MockClientGetter{ - servicesMap: serviceNamespaces, + servicesMap: serviceNamespaces, + endpointsMap: endpointNamespaces, } urls, err := GetServiceURLsForService(test.api, test.namespace, test.service, defaultTemplate) if err != nil && !test.err {