Skip to content

Commit ba7d3bb

Browse files
committed
Include port names in the service cmd's output
1 parent e974ce3 commit ba7d3bb

File tree

2 files changed

+40
-36
lines changed

2 files changed

+40
-36
lines changed

pkg/minikube/service/service.go

+31-29
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,20 @@ func (*K8sClientGetter) GetClientset(timeout time.Duration) (*kubernetes.Clients
9797
return client, nil
9898
}
9999

100-
// URL represents service URL
101-
type URL struct {
100+
// SvcURL represents a service URL. Each item in the URLs field combines the service URL with one of the configured
101+
// node ports. The PortNames field contains the configured names of the ports in the URLs field (sorted correspondingly -
102+
// first item in PortNames belongs to the first item in URLs).
103+
type SvcURL struct {
102104
Namespace string
103105
Name string
104106
URLs []string
107+
PortNames []string
105108
}
106109

107110
// URLs represents a list of URL
108-
type URLs []URL
111+
type URLs []SvcURL
109112

110-
// GetServiceURLs returns all the node port URLs for every service in a particular namespace
113+
// GetServiceURLs returns a SvcUrl object for every service in a particular namespace.
111114
// Accepts a template for formatting
112115
func GetServiceURLs(api libmachine.API, namespace string, t *template.Template) (URLs, error) {
113116
host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName())
@@ -132,52 +135,49 @@ func GetServiceURLs(api libmachine.API, namespace string, t *template.Template)
132135
return nil, err
133136
}
134137

135-
var serviceURLs []URL
138+
var serviceURLs []SvcURL
136139
for _, svc := range svcs.Items {
137-
urls, err := printURLsForService(client, ip, svc.Name, svc.Namespace, t)
140+
svcURL, err := printURLsForService(client, ip, svc.Name, svc.Namespace, t)
138141
if err != nil {
139142
return nil, err
140143
}
141-
serviceURLs = append(serviceURLs, URL{Namespace: svc.Namespace, Name: svc.Name, URLs: urls})
144+
serviceURLs = append(serviceURLs, svcURL)
142145
}
143146

144147
return serviceURLs, nil
145148
}
146149

147-
// GetServiceURLsForService returns all the node ports for a service in a namespace
148-
// with optional formatting
149-
func GetServiceURLsForService(api libmachine.API, namespace, service string, t *template.Template) ([]string, error) {
150+
// GetServiceURLsForService returns a SvcUrl object for a service in a namespace. Supports optional formatting.
151+
func GetServiceURLsForService(api libmachine.API, namespace, service string, t *template.Template) (SvcURL, error) {
150152
host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName())
151153
if err != nil {
152-
return nil, errors.Wrap(err, "Error checking if api exist and loading it")
154+
return SvcURL{}, errors.Wrap(err, "Error checking if api exist and loading it")
153155
}
154156

155157
ip, err := host.Driver.GetIP()
156158
if err != nil {
157-
return nil, errors.Wrap(err, "Error getting ip from host")
159+
return SvcURL{}, errors.Wrap(err, "Error getting ip from host")
158160
}
159161

160162
client, err := K8s.GetCoreClient()
161163
if err != nil {
162-
return nil, err
164+
return SvcURL{}, err
163165
}
164166

165167
return printURLsForService(client, ip, service, namespace, t)
166168
}
167169

168-
func printURLsForService(c typed_core.CoreV1Interface, ip, service, namespace string, t *template.Template) ([]string, error) {
170+
func printURLsForService(c typed_core.CoreV1Interface, ip, service, namespace string, t *template.Template) (SvcURL, error) {
169171
if t == nil {
170-
return nil, errors.New("Error, attempted to generate service url with nil --format template")
172+
return SvcURL{}, errors.New("Error, attempted to generate service url with nil --format template")
171173
}
172174

173-
s := c.Services(namespace)
174-
svc, err := s.Get(service, meta.GetOptions{})
175+
svc, err := c.Services(namespace).Get(service, meta.GetOptions{})
175176
if err != nil {
176-
return nil, errors.Wrapf(err, "service '%s' could not be found running", service)
177+
return SvcURL{}, errors.Wrapf(err, "service '%s' could not be found running", service)
177178
}
178179

179-
e := c.Endpoints(namespace)
180-
endpoints, err := e.Get(service, meta.GetOptions{})
180+
endpoints, err := c.Endpoints(namespace).Get(service, meta.GetOptions{})
181181
m := make(map[int32]string)
182182
if err == nil && endpoints != nil && len(endpoints.Subsets) > 0 {
183183
for _, ept := range endpoints.Subsets {
@@ -188,6 +188,7 @@ func printURLsForService(c typed_core.CoreV1Interface, ip, service, namespace st
188188
}
189189

190190
urls := []string{}
191+
portNames := []string{}
191192
for _, port := range svc.Spec.Ports {
192193
if port.NodePort > 0 {
193194
var doc bytes.Buffer
@@ -201,12 +202,13 @@ func printURLsForService(c typed_core.CoreV1Interface, ip, service, namespace st
201202
m[port.TargetPort.IntVal],
202203
})
203204
if err != nil {
204-
return nil, err
205+
return SvcURL{}, err
205206
}
206207
urls = append(urls, doc.String())
208+
portNames = append(portNames, m[port.TargetPort.IntVal])
207209
}
208210
}
209-
return urls, nil
211+
return SvcURL{Namespace: svc.Namespace, Name: svc.Name, URLs: urls, PortNames: portNames}, nil
210212
}
211213

212214
// CheckService checks if a service is listening on a port.
@@ -249,7 +251,7 @@ func OptionallyHTTPSFormattedURLString(bareURLString string, https bool) (string
249251
// "Namespace", "Name" and "URL" columns to a writer
250252
func PrintServiceList(writer io.Writer, data [][]string) {
251253
table := tablewriter.NewWriter(writer)
252-
table.SetHeader([]string{"Namespace", "Name", "URL"})
254+
table.SetHeader([]string{"Namespace", "Name", "Port", "URL"})
253255
table.SetBorders(tablewriter.Border{Left: true, Top: true, Right: true, Bottom: true})
254256
table.SetCenterSeparator("|")
255257
table.AppendBulk(data)
@@ -269,27 +271,27 @@ func WaitAndMaybeOpenService(api libmachine.API, namespace string, service strin
269271
return errors.Wrapf(err, "Could not find finalized endpoint being pointed to by %s", service)
270272
}
271273

272-
urls, err := GetServiceURLsForService(api, namespace, service, urlTemplate)
274+
serviceURL, err := GetServiceURLsForService(api, namespace, service, urlTemplate)
273275
if err != nil {
274276
return errors.Wrap(err, "Check that minikube is running and that you have specified the correct namespace")
275277
}
276278

277279
if !urlMode {
278280
var data [][]string
279-
if len(urls) == 0 {
280-
data = append(data, []string{namespace, service, "No node port"})
281+
if len(serviceURL.URLs) == 0 {
282+
data = append(data, []string{namespace, service, "", "No node port"})
281283
} else {
282-
data = append(data, []string{namespace, service, strings.Join(urls, "\n")})
284+
data = append(data, []string{namespace, service, strings.Join(serviceURL.PortNames, "\n"), strings.Join(serviceURL.URLs, "\n")})
283285
}
284286
PrintServiceList(os.Stdout, data)
285287
}
286288

287-
if len(urls) == 0 {
289+
if len(serviceURL.URLs) == 0 {
288290
out.T(out.Sad, "service {{.namespace_name}}/{{.service_name}} has no node port", out.V{"namespace_name": namespace, "service_name": service})
289291
return nil
290292
}
291293

292-
for _, bareURLString := range urls {
294+
for _, bareURLString := range serviceURL.URLs {
293295
urlString, isHTTPSchemedURL := OptionallyHTTPSFormattedURLString(bareURLString, https)
294296

295297
if urlMode || !isHTTPSchemedURL {

pkg/minikube/service/service_test.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -280,15 +280,15 @@ func TestPrintURLsForService(t *testing.T) {
280280
test := test
281281
t.Run(test.description, func(t *testing.T) {
282282
t.Parallel()
283-
urls, err := printURLsForService(client, "127.0.0.1", test.serviceName, test.namespace, test.tmpl)
283+
svcURL, err := printURLsForService(client, "127.0.0.1", test.serviceName, test.namespace, test.tmpl)
284284
if err != nil && !test.err {
285285
t.Errorf("Error: %v", err)
286286
}
287287
if err == nil && test.err {
288288
t.Errorf("Expected error but got none")
289289
}
290-
if !reflect.DeepEqual(urls, test.expectedOutput) {
291-
t.Errorf("\nExpected %v \nActual: %v \n\n", test.expectedOutput, urls)
290+
if !reflect.DeepEqual(svcURL.URLs, test.expectedOutput) {
291+
t.Errorf("\nExpected %v \nActual: %v \n\n", test.expectedOutput, svcURL.URLs)
292292
}
293293
})
294294
}
@@ -384,16 +384,18 @@ func TestGetServiceURLs(t *testing.T) {
384384
description: "correctly return serviceURLs",
385385
namespace: "default",
386386
api: defaultAPI,
387-
expected: []URL{
387+
expected: []SvcURL{
388388
{
389389
Namespace: "default",
390390
Name: "mock-dashboard",
391391
URLs: []string{"http://127.0.0.1:1111", "http://127.0.0.1:2222"},
392+
PortNames: []string{"port1", "port2"},
392393
},
393394
{
394395
Namespace: "default",
395396
Name: "mock-dashboard-no-ports",
396397
URLs: []string{},
398+
PortNames: []string{},
397399
},
398400
},
399401
},
@@ -477,15 +479,15 @@ func TestGetServiceURLsForService(t *testing.T) {
477479
servicesMap: serviceNamespaces,
478480
endpointsMap: endpointNamespaces,
479481
}
480-
urls, err := GetServiceURLsForService(test.api, test.namespace, test.service, defaultTemplate)
482+
svcURL, err := GetServiceURLsForService(test.api, test.namespace, test.service, defaultTemplate)
481483
if err != nil && !test.err {
482484
t.Errorf("Error GetServiceURLsForService %v", err)
483485
}
484486
if err == nil && test.err {
485487
t.Errorf("Test should have failed, but didn't")
486488
}
487-
if !reflect.DeepEqual(urls, test.expected) {
488-
t.Errorf("URLs did not match, expected %+v \n\n got %+v", test.expected, urls)
489+
if !reflect.DeepEqual(svcURL.URLs, test.expected) {
490+
t.Errorf("URLs did not match, expected %+v \n\n got %+v", test.expected, svcURL.URLs)
489491
}
490492
})
491493
}

0 commit comments

Comments
 (0)