Skip to content

Commit

Permalink
Setup port-forwarding for linkerd dashboard command (#2052)
Browse files Browse the repository at this point in the history
* Setup port-forwarding for linkerd dashboard command
* Output port-forward logs when --verbose flag is set

Signed-off-by: Kevin Lingerfelt <kl@buoyant.io>
  • Loading branch information
klingerf committed Jan 10, 2019
1 parent 1723982 commit ed3fbd7
Show file tree
Hide file tree
Showing 20 changed files with 272 additions and 262 deletions.
4 changes: 1 addition & 3 deletions Dockerfile-go-deps
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,4 @@ RUN CGO_ENABLED=0 GOOS=linux go install \
k8s.io/client-go/util/flowcontrol \
k8s.io/client-go/util/homedir \
k8s.io/client-go/util/integer \
k8s.io/client-go/util/jsonpath \
k8s.io/kubernetes/pkg/kubectl/proxy \
k8s.io/kubernetes/pkg/kubectl/util
k8s.io/client-go/util/jsonpath
39 changes: 15 additions & 24 deletions Gopkg.lock
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@
revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29"
version = "v3.1.0"

[[projects]]
digest = "1:59be0b37b12a8cdb8fedd44f6ccdd4aec6735ad4fb10bf19bb99ae5d1c701dda"
name = "github.com/docker/spdystream"
packages = [
".",
"spdy",
]
pruneopts = ""
revision = "449fdfce4d962303d702fec724ef0ad181c92528"

[[projects]]
digest = "1:b13707423743d41665fd23f0c36b2f37bb49c30e94adb813319c44188a51ba22"
name = "github.com/ghodss/yaml"
Expand Down Expand Up @@ -312,14 +322,6 @@
revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd"
version = "1.0.1"

[[projects]]
branch = "master"
digest = "1:d33ce379780d7c43405b9251289493cabada82f6bf9ab35eea6915d04f6ac8e0"
name = "github.com/mxk/go-flowrate"
packages = ["flowrate"]
pruneopts = ""
revision = "cca7078d478f8520f85629ad7c68962d31ed7682"

[[projects]]
branch = "master"
digest = "1:1a25d906193d34ce43e96fcab1a2de2b90e0242f9b0c176564db1b268bf48ea5"
Expand Down Expand Up @@ -461,8 +463,6 @@
packages = [
"context",
"context/ctxhttp",
"html",
"html/atom",
"http2",
"http2/hpack",
"idna",
Expand Down Expand Up @@ -689,11 +689,11 @@
"pkg/util/errors",
"pkg/util/framer",
"pkg/util/httpstream",
"pkg/util/httpstream/spdy",
"pkg/util/intstr",
"pkg/util/json",
"pkg/util/mergepatch",
"pkg/util/net",
"pkg/util/proxy",
"pkg/util/runtime",
"pkg/util/sets",
"pkg/util/strategicpatch",
Expand Down Expand Up @@ -866,8 +866,10 @@
"tools/clientcmd/api/v1",
"tools/metrics",
"tools/pager",
"tools/portforward",
"tools/reference",
"transport",
"transport/spdy",
"util/buffer",
"util/cert",
"util/connrotation",
Expand Down Expand Up @@ -935,18 +937,6 @@
pruneopts = ""
revision = "d8ea2fe547a448256204cfc68dfee7b26c720acb"

[[projects]]
digest = "1:7107d2e83c67ac0dbd9b62e8e2bfe1a75b194864ea4fe30778f4842151cd356d"
name = "k8s.io/kubernetes"
packages = [
"pkg/apis/core",
"pkg/kubectl/proxy",
"pkg/kubectl/util",
]
pruneopts = ""
revision = "b1b29978270dc22fecc592ac55d903350454310a"
version = "v1.11.1"

[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
Expand Down Expand Up @@ -1023,14 +1013,15 @@
"k8s.io/client-go/testing",
"k8s.io/client-go/tools/cache",
"k8s.io/client-go/tools/clientcmd",
"k8s.io/client-go/tools/portforward",
"k8s.io/client-go/transport/spdy",
"k8s.io/client-go/util/flowcontrol",
"k8s.io/client-go/util/workqueue",
"k8s.io/code-generator/cmd/client-gen",
"k8s.io/code-generator/cmd/deepcopy-gen",
"k8s.io/code-generator/cmd/defaulter-gen",
"k8s.io/code-generator/cmd/informer-gen",
"k8s.io/code-generator/cmd/lister-gen",
"k8s.io/kubernetes/pkg/kubectl/proxy",
]
solver-name = "gps-cdcl"
solver-version = 1
24 changes: 6 additions & 18 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ required = [
name = "k8s.io/apimachinery"
version = "kubernetes-1.11.1"

[[constraint]]
name = "k8s.io/kubernetes"
version = "v1.11.1"

[[constraint]]
name = "github.com/sirupsen/logrus"
version = "v1.0.3"
Expand All @@ -60,26 +56,18 @@ required = [
name = "github.com/go-openapi/spec"
version = "v0.17.2"
#
# k8s.io/kubernetes dependency fixes
# taken from https://github.com/kubernetes/kubernetes/blob/master/Godeps/Godeps.json
# k8s.io/client-go dependency fixes
# taken from https://github.com/kubernetes/client-go/blob/kubernetes-1.11.1/Godeps/Godeps.json
#

[[override]]
name = "github.com/docker/distribution"
revision = "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c"

[[override]]
name = "github.com/docker/docker"
revision = "4f3616fb1c112e206b88cb7a9922bf49067a7756"

[[override]]
name = "github.com/russross/blackfriday"
revision = "300106c228d52c8941d4b3de6054a6062a86dda3"

[[override]]
name = "github.com/json-iterator/go"
revision = "f2b4162afba35581b6d4a50d3b8f34e33c144682"

[[override]]
name = "github.com/Azure/go-autorest"
revision = "1ff28809256a84bb6966640ff3d0371af82ccba4"

[[override]]
name = "github.com/docker/spdystream"
revision = "449fdfce4d962303d702fec724ef0ad181c92528"
2 changes: 1 addition & 1 deletion cli/Dockerfile-bin
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## compile binaries
FROM gcr.io/linkerd-io/go-deps:4b31aa9b as golang
FROM gcr.io/linkerd-io/go-deps:f95a60fe as golang
WORKDIR /go/src/github.com/linkerd/linkerd2
COPY cli cli
COPY controller/k8s controller/k8s
Expand Down
99 changes: 60 additions & 39 deletions cli/cmd/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"fmt"
"os"
"os/signal"
"time"

"github.com/linkerd/linkerd2/pkg/k8s"
Expand All @@ -20,19 +21,25 @@ const (

// showURL displays dashboard URLs without opening a browser.
showURL = "url"

// webDeployment is the name of the web deployment in cli/install/template.go
webDeployment = "linkerd-web"

// webPort is the http port from the web pod spec in cli/install/template.go
webPort = 8084
)

type dashboardOptions struct {
dashboardProxyPort int
dashboardShow string
wait time.Duration
port int
show string
wait time.Duration
}

func newDashboardOptions() *dashboardOptions {
return &dashboardOptions{
dashboardProxyPort: 0,
dashboardShow: showLinkerd,
wait: 300 * time.Second,
port: 0,
show: showLinkerd,
wait: 300 * time.Second,
}
}

Expand All @@ -43,52 +50,72 @@ func newCmdDashboard() *cobra.Command {
Use: "dashboard [flags]",
Short: "Open the Linkerd dashboard in a web browser",
RunE: func(cmd *cobra.Command, args []string) error {
if options.dashboardProxyPort < 0 {
return fmt.Errorf("port must be greater than or equal to zero, was %d", options.dashboardProxyPort)
if options.port < 0 {
return fmt.Errorf("port must be greater than or equal to zero, was %d", options.port)
}

if options.dashboardShow != showLinkerd && options.dashboardShow != showGrafana && options.dashboardShow != showURL {
if options.show != showLinkerd && options.show != showGrafana && options.show != showURL {
return fmt.Errorf("unknown value for 'show' param, was: %s, must be one of: %s, %s, %s",
options.dashboardShow, showLinkerd, showGrafana, showURL)
options.show, showLinkerd, showGrafana, showURL)
}

kubernetesProxy, err := k8s.NewProxy(kubeconfigPath, kubeContext, options.dashboardProxyPort)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to initialize proxy: %s\n", err)
os.Exit(1)
}
// ensure we can connect to the public API before starting the proxy
validatedPublicAPIClient(time.Now().Add(options.wait), true)

url, err := kubernetesProxy.URLFor(controlPlaneNamespace, "/services/linkerd-web:http/proxy/")
wait := make(chan struct{}, 1)
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt)
defer signal.Stop(signals)

portforward, err := k8s.NewPortForward(
kubeconfigPath,
kubeContext,
controlPlaneNamespace,
webDeployment,
options.port,
webPort,
verbose,
)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to generate URL for dashboard: %s\n", err)
fmt.Fprintf(os.Stderr, "Failed to initialize port-forward: %s\n", err)
os.Exit(1)
}

grafanaURL, err := kubernetesProxy.URLFor(controlPlaneNamespace, "/services/linkerd-web:http/proxy/grafana/")
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to generate URL for Grafana: %s\n", err)
os.Exit(1)
}
go func() {
err := portforward.Run()
if err != nil {
fmt.Fprintf(os.Stderr, "Error running port-forward: %s", err)
os.Exit(1)
}
close(wait)
}()

// ensure we can connect to the public API before starting the proxy
validatedPublicAPIClient(time.Now().Add(options.wait), true)
go func() {
<-signals
portforward.Stop()
}()

<-portforward.Ready()

fmt.Printf("Linkerd dashboard available at:\n%s\n", url.String())
fmt.Printf("Grafana dashboard available at:\n%s\n", grafanaURL.String())
webURL := portforward.URLFor("")
grafanaURL := portforward.URLFor("/grafana")

switch options.dashboardShow {
fmt.Printf("Linkerd dashboard available at:\n%s\n", webURL)
fmt.Printf("Grafana dashboard available at:\n%s\n", grafanaURL)

switch options.show {
case showLinkerd:
fmt.Println("Opening Linkerd dashboard in the default browser")

err = browser.OpenURL(url.String())
err = browser.OpenURL(webURL)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to open Linkerd URL %s in the default browser: %s", url, err)
fmt.Fprintf(os.Stderr, "Failed to open Linkerd URL %s in the default browser: %s", webURL, err)
os.Exit(1)
}
case showGrafana:
fmt.Println("Opening Grafana dashboard in the default browser")

err = browser.OpenURL(grafanaURL.String())
err = browser.OpenURL(grafanaURL)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to open Grafana URL %s in the default browser: %s", grafanaURL, err)
os.Exit(1)
Expand All @@ -97,21 +124,15 @@ func newCmdDashboard() *cobra.Command {
// no-op, we already printed the URLs
}

// blocks until killed
err = kubernetesProxy.Run()
if err != nil {
fmt.Fprintf(os.Stderr, "Error running proxy: %s", err)
os.Exit(1)
}

<-wait
return nil
},
}

cmd.Args = cobra.NoArgs
// This is identical to what `kubectl proxy --help` reports, `--port 0` indicates a random port.
cmd.PersistentFlags().IntVarP(&options.dashboardProxyPort, "port", "p", options.dashboardProxyPort, "The port on which to run the proxy (when set to 0, a random port will be used)")
cmd.PersistentFlags().StringVar(&options.dashboardShow, "show", options.dashboardShow, "Open a dashboard in a browser or show URLs in the CLI (one of: linkerd, grafana, url)")
cmd.PersistentFlags().IntVarP(&options.port, "port", "p", options.port, "The local port on which to serve requests (when set to 0, a random port will be used)")
cmd.PersistentFlags().StringVar(&options.show, "show", options.show, "Open a dashboard in a browser or show URLs in the CLI (one of: linkerd, grafana, url)")
cmd.PersistentFlags().DurationVar(&options.wait, "wait", options.wait, "Wait for dashboard to become available if it's not available when the command is run")

return cmd
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/testdata/install_default.golden
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ data:
instance_name = linkerd-grafana

[server]
root_url = %(protocol)s://%(domain)s:/api/v1/namespaces/linkerd/services/linkerd-web:http/proxy/grafana/
root_url = %(protocol)s://%(domain)s:/grafana/

[auth]
disable_login_form = true
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/testdata/install_ha_output.golden
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ data:
instance_name = linkerd-grafana

[server]
root_url = %(protocol)s://%(domain)s:/api/v1/namespaces/linkerd/services/linkerd-web:http/proxy/grafana/
root_url = %(protocol)s://%(domain)s:/grafana/

[auth]
disable_login_form = true
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/testdata/install_ha_with_overrides_output.golden
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ data:
instance_name = linkerd-grafana

[server]
root_url = %(protocol)s://%(domain)s:/api/v1/namespaces/linkerd/services/linkerd-web:http/proxy/grafana/
root_url = %(protocol)s://%(domain)s:/grafana/

[auth]
disable_login_form = true
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/testdata/install_output.golden
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ data:
instance_name = linkerd-grafana

[server]
root_url = %(protocol)s://%(domain)s:/api/v1/namespaces/Namespace/services/linkerd-web:http/proxy/grafana/
root_url = %(protocol)s://%(domain)s:/grafana/

[auth]
disable_login_form = true
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/testdata/install_single_namespace_output.golden
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ data:
instance_name = linkerd-grafana

[server]
root_url = %(protocol)s://%(domain)s:/api/v1/namespaces/Namespace/services/linkerd-web:http/proxy/grafana/
root_url = %(protocol)s://%(domain)s:/grafana/

[auth]
disable_login_form = true
Expand Down
2 changes: 1 addition & 1 deletion cli/install/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ data:
instance_name = linkerd-grafana
[server]
root_url = %(protocol)s://%(domain)s:/api/v1/namespaces/{{.Namespace}}/services/linkerd-web:http/proxy/grafana/
root_url = %(protocol)s://%(domain)s:/grafana/
[auth]
disable_login_form = true
Expand Down
2 changes: 1 addition & 1 deletion controller/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## compile controller services
FROM gcr.io/linkerd-io/go-deps:4b31aa9b as golang
FROM gcr.io/linkerd-io/go-deps:f95a60fe as golang
WORKDIR /go/src/github.com/linkerd/linkerd2
COPY controller/gen controller/gen
COPY pkg pkg
Expand Down
Loading

0 comments on commit ed3fbd7

Please sign in to comment.