1 package cmd
2
3 import (
4 "fmt"
5 "os"
6 "os/signal"
7 "time"
8
9 "github.com/linkerd/linkerd2/pkg/healthcheck"
10 "github.com/linkerd/linkerd2/pkg/k8s"
11 "github.com/pkg/browser"
12 "github.com/spf13/cobra"
13 )
14
15 const (
16
17
18 jaegerDeployment = "jaeger"
19
20
21 webPort = 16686
22
23
24 defaultHost = "localhost"
25
26
27 defaultPort = 16686
28 )
29
30
31
32 type dashboardOptions struct {
33 host string
34 port int
35 showURL bool
36 wait time.Duration
37 }
38
39
40
41
42
43
44 func newDashboardOptions() *dashboardOptions {
45 return &dashboardOptions{
46 host: defaultHost,
47 port: defaultPort,
48 wait: 300 * time.Second,
49 }
50 }
51
52
53
54
55 func newCmdDashboard() *cobra.Command {
56 options := newDashboardOptions()
57
58 cmd := &cobra.Command{
59 Use: "dashboard [flags]",
60 Short: "Open the Jaeger extension dashboard in a web browser",
61 Args: cobra.NoArgs,
62 RunE: func(cmd *cobra.Command, args []string) error {
63 if options.port < 0 {
64 return fmt.Errorf("port must be greater than or equal to zero, was %d", options.port)
65 }
66
67 checkForJaeger(healthcheck.Options{
68 ControlPlaneNamespace: controlPlaneNamespace,
69 KubeConfig: kubeconfigPath,
70 Impersonate: impersonate,
71 ImpersonateGroup: impersonateGroup,
72 KubeContext: kubeContext,
73 APIAddr: apiAddr,
74 RetryDeadline: time.Now().Add(options.wait),
75 })
76
77 k8sAPI, err := k8s.NewAPI(kubeconfigPath, kubeContext, impersonate, impersonateGroup, 0)
78 if err != nil {
79 return err
80 }
81
82 jaegerNamespace, err := k8sAPI.GetNamespaceWithExtensionLabel(cmd.Context(), JaegerExtensionName)
83 if err != nil {
84 return err
85 }
86
87 signals := make(chan os.Signal, 1)
88 signal.Notify(signals, os.Interrupt)
89 defer signal.Stop(signals)
90
91 portforward, err := k8s.NewPortForward(
92 cmd.Context(),
93 k8sAPI,
94 jaegerNamespace.Name,
95 jaegerDeployment,
96 options.host,
97 options.port,
98 webPort,
99 verbose,
100 )
101 if err != nil {
102 fmt.Fprintf(os.Stderr, "Failed to initialize port-forward: %s\n", err)
103 os.Exit(1)
104 }
105
106 if err = portforward.Init(); err != nil {
107
108 fmt.Fprintf(os.Stderr, "Error running port-forward: %s\nCheck for `jaeger dashboard` running in other terminal sessions, or use the `--port` flag.\n", err)
109 os.Exit(1)
110 }
111
112 go func() {
113 <-signals
114 portforward.Stop()
115 }()
116
117 webURL := portforward.URLFor("")
118
119 fmt.Printf("Jaeger extension dashboard available at:\n%s\n", webURL)
120
121 if !options.showURL {
122 err = browser.OpenURL(webURL)
123 if err != nil {
124 fmt.Fprintln(os.Stderr, "Failed to open dashboard automatically")
125 fmt.Fprintf(os.Stderr, "Visit %s in your browser to view the dashboard\n", webURL)
126 }
127 }
128
129 <-portforward.GetStop()
130 return nil
131 },
132 }
133
134
135 cmd.PersistentFlags().StringVar(&options.host, "address", options.host, "The address at which to serve requests")
136 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)")
137 cmd.PersistentFlags().BoolVar(&options.showURL, "show-url", options.showURL, "show only URL in the CLI, and do not open the browser")
138 cmd.PersistentFlags().DurationVar(&options.wait, "wait", options.wait, "Wait for dashboard to become available if it's not available when the command is run")
139
140 return cmd
141 }
142
View as plain text