From 3bf4b5ef737ebcf0750c7ad8ba28cf7474a3f65c Mon Sep 17 00:00:00 2001 From: LiuFeng <31612033+imneov@users.noreply.github.com> Date: Fri, 30 Sep 2022 12:18:41 +0800 Subject: [PATCH] Feat/dashboard supports random port (#874) --- cmd/dashboard.go | 8 ++++++-- pkg/kubernetes/portforward.go | 35 +++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/cmd/dashboard.go b/cmd/dashboard.go index c36472060..a093dca3f 100644 --- a/cmd/dashboard.go +++ b/cmd/dashboard.go @@ -15,6 +15,7 @@ package cmd import ( "fmt" + "net" "os" "os/signal" @@ -72,6 +73,9 @@ dapr dashboard -k -p 9999 -a 0.0.0.0 # Port forward to dashboard in Kubernetes using a port dapr dashboard -k -p 9999 + +# Port forward to dashboard in Kubernetes using a random port which is free. +dapr dashboard -k -p 0 `, Run: func(cmd *cobra.Command, args []string) { if dashboardVersionCmd { @@ -84,7 +88,7 @@ dapr dashboard -k -p 9999 os.Exit(1) } - if dashboardLocalPort <= 0 { + if dashboardLocalPort < 0 { print.FailureStatusEvent(os.Stderr, "Invalid port: %v", dashboardLocalPort) os.Exit(1) } @@ -161,7 +165,7 @@ dapr dashboard -k -p 9999 }() // url for dashboard after port forwarding. - var webURL string = fmt.Sprintf("http://%s:%d", dashboardHost, dashboardLocalPort) //nolint:nosprintfhostport + var webURL string = net.JoinHostPort(dashboardHost, fmt.Sprint(portForward.LocalPort)) print.InfoStatusEvent(os.Stdout, fmt.Sprintf("Dapr dashboard found in namespace:\t%s", foundNamespace)) print.InfoStatusEvent(os.Stdout, fmt.Sprintf("Dapr dashboard available at:\t%s\n", webURL)) diff --git a/pkg/kubernetes/portforward.go b/pkg/kubernetes/portforward.go index e96dbc210..484b39e1a 100644 --- a/pkg/kubernetes/portforward.go +++ b/pkg/kubernetes/portforward.go @@ -52,7 +52,7 @@ func NewPortForward( ) (*PortForward, error) { client, err := k8s.NewForConfig(config) if err != nil { - return nil, err + return nil, fmt.Errorf("can't create Clientset for %q: %w", deployName, err) } podList, err := ListPods(client, namespace, nil) @@ -94,12 +94,13 @@ func NewPortForward( }, nil } -// run creates port-forward connection and blocks -// until Stop() is called. -func (pf *PortForward) run() error { +// Init creates and runs a port-forward connection. +// This function blocks until connection is established. +// Note: Caller should call Stop() to finish the connection. +func (pf *PortForward) Init() error { transport, upgrader, err := spdy.RoundTripperFor(pf.Config) if err != nil { - return err + return fmt.Errorf("cannot connect to Kubernetes cluster: %w", err) } out := io.Discard @@ -114,27 +115,29 @@ func (pf *PortForward) run() error { fw, err := portforward.NewOnAddresses(dialer, []string{pf.Host}, ports, pf.StopCh, pf.ReadyCh, out, errOut) if err != nil { - return err + return fmt.Errorf("cannot create PortForwarder: %w", err) } - return fw.ForwardPorts() -} - -// Init creates and runs a port-forward connection. -// This function blocks until connection is established. -// Note: Caller should call Stop() to finish the connection. -func (pf *PortForward) Init() error { failure := make(chan error) - go func() { - if err := pf.run(); err != nil { + if err := fw.ForwardPorts(); err != nil { failure <- err } }() select { - // if `pf.run()` succeeds, block until terminated. + // if `fw.ForwardPorts()` succeeds, block until terminated. case <-pf.ReadyCh: + ports, err := fw.GetPorts() + if err != nil { + return fmt.Errorf("can not get the local and remote ports: %w", err) + } + if len(ports) == 0 { + return fmt.Errorf("can not get the local and remote ports: error getting ports length") + } + + pf.LocalPort = int(ports[0].Local) + pf.RemotePort = int(ports[0].Remote) // if failure, causing a receive `<-failure` and returns the error. case err := <-failure: