Added functionality to read/open multiple ports via service cmd. Also
updated tests and help text for multiple ports. Also updated docs.pull/729/head
parent
55fd539300
commit
bc1f5db71a
|
@ -22,6 +22,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/browser"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
|
@ -52,19 +53,23 @@ var dashboardCmd = &cobra.Command{
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
url, err := cluster.GetServiceURL(api, namespace, service, nil)
|
||||
urls, err := cluster.GetServiceURLs(api, namespace, service, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
fmt.Fprintln(os.Stderr, "Check that minikube is running.")
|
||||
os.Exit(1)
|
||||
}
|
||||
if len(urls) == 0 {
|
||||
errMsg := "There appears to be no url associated with dashboard, this is not expected, exiting"
|
||||
glog.Infoln(errMsg)
|
||||
os.Exit(1)
|
||||
}
|
||||
if dashboardURLMode {
|
||||
fmt.Fprintln(os.Stdout, url)
|
||||
fmt.Fprintln(os.Stdout, urls[0])
|
||||
} else {
|
||||
fmt.Fprintln(os.Stdout, "Opening kubernetes dashboard in default browser...")
|
||||
browser.OpenURL(url)
|
||||
browser.OpenURL(urls[0])
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ var (
|
|||
// serviceCmd represents the service command
|
||||
var serviceCmd = &cobra.Command{
|
||||
Use: "service [flags] SERVICE",
|
||||
Short: "Gets the kubernetes URL for the specified service in your local cluster",
|
||||
Long: `Gets the kubernetes URL for the specified service in your local cluster`,
|
||||
Short: "Gets the kubernetes URL(s) for the specified service in your local cluster",
|
||||
Long: `Gets the kubernetes URL(s) for the specified service in your local cluster. In the case of multiple URLs they will be printed one at a time`,
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
t, err := template.New("serviceURL").Parse(serviceURLFormat)
|
||||
if err != nil {
|
||||
|
@ -76,20 +76,22 @@ var serviceCmd = &cobra.Command{
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
url, err := cluster.GetServiceURL(api, namespace, service, serviceURLTemplate)
|
||||
urls, err := cluster.GetServiceURLs(api, namespace, service, serviceURLTemplate)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
fmt.Fprintln(os.Stderr, "Check that minikube is running and that you have specified the correct namespace (-n flag).")
|
||||
os.Exit(1)
|
||||
}
|
||||
if https {
|
||||
url = strings.Replace(url, "http", "https", 1)
|
||||
}
|
||||
if serviceURLMode {
|
||||
fmt.Fprintln(os.Stdout, url)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stdout, "Opening kubernetes service "+namespace+"/"+service+" in default browser...")
|
||||
browser.OpenURL(url)
|
||||
for _, url := range urls {
|
||||
if https {
|
||||
url = strings.Replace(url, "http", "https", 1)
|
||||
}
|
||||
if serviceURLMode || !strings.HasPrefix(url, "http") {
|
||||
fmt.Fprintln(os.Stdout, url)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stdout, "Opening kubernetes service "+namespace+"/"+service+" in default browser...")
|
||||
browser.OpenURL(url)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -99,7 +101,7 @@ func init() {
|
|||
serviceCmd.Flags().BoolVar(&serviceURLMode, "url", false, "Display the kubernetes service URL in the CLI instead of opening it in the default browser")
|
||||
serviceCmd.Flags().BoolVar(&https, "https", false, "Open the service URL with https instead of http")
|
||||
|
||||
serviceCmd.PersistentFlags().StringVar(&serviceURLFormat, "format", "http://{{.IP}}:{{.Port}}", "Format to output service URL in")
|
||||
serviceCmd.PersistentFlags().StringVar(&serviceURLFormat, "format", "http://{{.IP}}:{{.Port}}", "Format to output service URL in. This format will be applied to each url individually and they will be printed one at a time.")
|
||||
|
||||
RootCmd.AddCommand(serviceCmd)
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ Minikube is a CLI tool that provisions and manages single-node Kubernetes cluste
|
|||
* [minikube get-k8s-versions](minikube_get-k8s-versions.md) - Gets the list of available kubernetes versions available for minikube.
|
||||
* [minikube ip](minikube_ip.md) - Retrieve the IP address of the running cluster.
|
||||
* [minikube logs](minikube_logs.md) - Gets the logs of the running localkube instance, used for debugging minikube, not user code.
|
||||
* [minikube service](minikube_service.md) - Gets the kubernetes URL for the specified service in your local cluster
|
||||
* [minikube service](minikube_service.md) - Gets the kubernetes URL(s) for the specified service in your local cluster
|
||||
* [minikube ssh](minikube_ssh.md) - Log into or run a command on a machine with SSH; similar to 'docker-machine ssh'
|
||||
* [minikube start](minikube_start.md) - Starts a local kubernetes cluster.
|
||||
* [minikube status](minikube_status.md) - Gets the status of a local kubernetes cluster.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
## minikube service
|
||||
|
||||
Gets the kubernetes URL for the specified service in your local cluster
|
||||
Gets the kubernetes URL(s) for the specified service in your local cluster
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Gets the kubernetes URL for the specified service in your local cluster
|
||||
Gets the kubernetes URL(s) for the specified service in your local cluster. In the case of multiple URLs they will be printed one at a time
|
||||
|
||||
```
|
||||
minikube service [flags] SERVICE
|
||||
|
@ -14,7 +14,7 @@ minikube service [flags] SERVICE
|
|||
### Options
|
||||
|
||||
```
|
||||
--format string Format to output service URL in (default "http://{{.IP}}:{{.Port}}")
|
||||
--format string Format to output service URL in. This format will be applied to each url individually and they will be printed one at a time. (default "http://{{.IP}}:{{.Port}}")
|
||||
--https Open the service URL with https instead of http
|
||||
-n, --namespace string The service namespace (default "default")
|
||||
--url Display the kubernetes service URL in the CLI instead of opening it in the default browser
|
||||
|
|
|
@ -27,7 +27,6 @@ import (
|
|||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
@ -513,50 +512,54 @@ func CreateSSHShell(api libmachine.API, args []string) error {
|
|||
|
||||
type ipPort struct {
|
||||
IP string
|
||||
Port int
|
||||
Port int32
|
||||
}
|
||||
|
||||
func GetServiceURL(api libmachine.API, namespace, service string, t *template.Template) (string, error) {
|
||||
func GetServiceURLs(api libmachine.API, namespace, service string, t *template.Template) ([]string, error) {
|
||||
host, err := CheckIfApiExistsAndLoad(api)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "Error checking if api exist and loading it")
|
||||
return nil, errors.Wrap(err, "Error checking if api exist and loading it")
|
||||
}
|
||||
|
||||
ip, err := host.Driver.GetIP()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "Error getting ip from host")
|
||||
return nil, errors.Wrap(err, "Error getting ip from host")
|
||||
}
|
||||
|
||||
client, err := GetKubernetesClient()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return getServiceURLWithClient(client, ip, namespace, service, t)
|
||||
return getServiceURLsWithClient(client, ip, namespace, service, t)
|
||||
}
|
||||
|
||||
func getServiceURLWithClient(client *unversioned.Client, ip, namespace, service string, t *template.Template) (string, error) {
|
||||
port, err := getServicePort(client, namespace, service)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
func getServiceURLsWithClient(client *unversioned.Client, ip, namespace, service string, t *template.Template) ([]string, error) {
|
||||
if t == nil {
|
||||
return fmt.Sprintf("http://%s", net.JoinHostPort(ip, strconv.Itoa(port))), nil
|
||||
return nil, errors.New("Error, attempted to generate service url with nil --format template")
|
||||
}
|
||||
|
||||
var doc bytes.Buffer
|
||||
err = t.Execute(&doc, ipPort{ip, port})
|
||||
ports, err := getServicePorts(client, namespace, service)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
urls := []string{}
|
||||
for _, port := range ports {
|
||||
|
||||
u, err := url.Parse(doc.String())
|
||||
if err != nil {
|
||||
return "", err
|
||||
var doc bytes.Buffer
|
||||
err = t.Execute(&doc, ipPort{ip, port})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u, err := url.Parse(doc.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
urls = append(urls, u.String())
|
||||
}
|
||||
|
||||
return u.String(), nil
|
||||
return urls, nil
|
||||
}
|
||||
|
||||
type serviceGetter interface {
|
||||
|
@ -568,9 +571,9 @@ type endpointGetter interface {
|
|||
Get(name string) (*kubeapi.Endpoints, error)
|
||||
}
|
||||
|
||||
func getServicePort(client *unversioned.Client, namespace, service string) (int, error) {
|
||||
func getServicePorts(client *unversioned.Client, namespace, service string) ([]int32, error) {
|
||||
services := client.Services(namespace)
|
||||
return getServicePortFromServiceGetter(services, service)
|
||||
return getServicePortsFromServiceGetter(services, service)
|
||||
}
|
||||
|
||||
type MissingNodePortError struct {
|
||||
|
@ -589,19 +592,21 @@ func getServiceFromServiceGetter(services serviceGetter, service string) (*kubea
|
|||
return svc, nil
|
||||
}
|
||||
|
||||
func getServicePortFromServiceGetter(services serviceGetter, service string) (int, error) {
|
||||
func getServicePortsFromServiceGetter(services serviceGetter, service string) ([]int32, error) {
|
||||
svc, err := getServiceFromServiceGetter(services, service)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return nil, err
|
||||
}
|
||||
nodePort := 0
|
||||
var nodePorts []int32
|
||||
if len(svc.Spec.Ports) > 0 {
|
||||
nodePort = int(svc.Spec.Ports[0].NodePort)
|
||||
for _, port := range svc.Spec.Ports {
|
||||
nodePorts = append(nodePorts, port.NodePort)
|
||||
}
|
||||
}
|
||||
if nodePort == 0 {
|
||||
return 0, MissingNodePortError{svc}
|
||||
if len(nodePorts) == 0 {
|
||||
return nil, MissingNodePortError{svc}
|
||||
}
|
||||
return nodePort, nil
|
||||
return nodePorts, nil
|
||||
}
|
||||
|
||||
func GetKubernetesClient() (*unversioned.Client, error) {
|
||||
|
|
|
@ -551,27 +551,30 @@ func (mockServiceGetter *MockServiceGetter) List(options api.ListOptions) (*api.
|
|||
return &services, nil
|
||||
}
|
||||
|
||||
func TestGetDashboardURL(t *testing.T) {
|
||||
func TestGetServiceURLs(t *testing.T) {
|
||||
mockServiceGetter := NewMockServiceGetter()
|
||||
nodeport := api.ServicePort{
|
||||
NodePort: 1234,
|
||||
}
|
||||
expected := []int32{1111, 2222}
|
||||
mockDashboardService := api.Service{
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{nodeport},
|
||||
Ports: []api.ServicePort{
|
||||
{
|
||||
NodePort: expected[0],
|
||||
}, {
|
||||
NodePort: expected[1],
|
||||
}},
|
||||
},
|
||||
}
|
||||
mockServiceGetter.services["kubernetes-dashboard"] = mockDashboardService
|
||||
mockServiceGetter.services["mock-service"] = mockDashboardService
|
||||
|
||||
port, err := getServicePortFromServiceGetter(mockServiceGetter, "kubernetes-dashboard")
|
||||
ports, err := getServicePortsFromServiceGetter(mockServiceGetter, "mock-service")
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting dashboard port from api: Error: %s", err)
|
||||
t.Fatalf("Error getting mock-service ports from api: Error: %s", err)
|
||||
}
|
||||
expected := 1234
|
||||
if port != expected {
|
||||
t.Fatalf("Error getting dashboard port from api: Expected: %d, Got: %d", port, expected)
|
||||
for i := range ports {
|
||||
if ports[i] != expected[i] {
|
||||
t.Fatalf("Error getting mock-service port from api: Expected: %d, Got: %d", ports[0], expected)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetServiceURLWithoutNodePort(t *testing.T) {
|
||||
|
@ -579,7 +582,7 @@ func TestGetServiceURLWithoutNodePort(t *testing.T) {
|
|||
mockDashboardService := api.Service{}
|
||||
mockServiceGetter.services["mock-service"] = mockDashboardService
|
||||
|
||||
_, err := getServicePortFromServiceGetter(mockServiceGetter, "mock-service")
|
||||
_, err := getServicePortsFromServiceGetter(mockServiceGetter, "mock-service")
|
||||
if err == nil {
|
||||
t.Fatalf("Expected error getting service with no node port")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue