diff --git a/README.md b/README.md index 1643349..ba6aaae 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,8 @@ You can see the list of available command-line flags by running `helm dashboard By default, the web server is only available locally. You can change that by specifying `HD_BIND` environment variable to the desired value. For example, `0.0.0.0` would bind to all IPv4 addresses or `[::0]` would be all IPv6 addresses. +This can also be specified using flag `--bind `, for example `--bind=0.0.0.0` or `--bind 0.0.0.0`. +> Precedence order: flag `--bind=` > env `HD_BIND=` > default value `localhost` If your port 8080 is busy, you can specify a different port to use via `--port ` command-line flag. diff --git a/go.mod b/go.mod index c14d18b..9e36fad 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/hashicorp/go-version v1.6.0 github.com/hexops/gotextdiff v1.0.3 github.com/jessevdk/go-flags v1.5.0 + github.com/olekukonko/tablewriter v0.0.5 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 github.com/sirupsen/logrus v1.9.0 gopkg.in/yaml.v3 v3.0.1 @@ -31,7 +32,6 @@ require ( github.com/mattn/go-runewidth v0.0.9 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml/v2 v2.0.3 // indirect github.com/ugorji/go/codec v1.2.7 // indirect golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 // indirect diff --git a/main.go b/main.go index a053cfd..6a19ce4 100644 --- a/main.go +++ b/main.go @@ -2,12 +2,13 @@ package main import ( "fmt" + "os" + "github.com/gin-gonic/gin" "github.com/jessevdk/go-flags" "github.com/komodorio/helm-dashboard/pkg/dashboard" "github.com/pkg/browser" log "github.com/sirupsen/logrus" - "os" ) var ( @@ -17,22 +18,35 @@ var ( ) type options struct { - Version bool `long:"version" description:"Show tool version"` - Verbose bool `short:"v" long:"verbose" description:"Show verbose debug information"` - NoBrowser bool `short:"b" long:"no-browser" description:"Do not attempt to open Web browser upon start"` - NoTracking bool `long:"no-analytics" description:"Disable user analytics (GA, DataDog etc.)"` - - Port uint `short:"p" long:"port" description:"Port to start server on" default:"8080"` // TODO: better default port to clash less? - - Namespace string `short:"n" long:"namespace" description:"Limit operations to a specific namespace"` + Version bool `long:"version" description:"Show tool version"` + Verbose bool `short:"v" long:"verbose" description:"Show verbose debug information"` + NoBrowser bool `short:"b" long:"no-browser" description:"Do not attempt to open Web browser upon start"` + NoTracking bool `long:"no-analytics" description:"Disable user analytics (GA, DataDog etc.)"` + BindHost string `long:"bind" description:"Host binding to start server (default: localhost)"` // default should be printed but not assigned as the precedence: flag > env > default + Port uint `short:"p" long:"port" description:"Port to start server on" default:"8080"` // TODO: better default port to clash less? + Namespace string `short:"n" long:"namespace" description:"Limit operations to a specific namespace"` } func main() { opts := parseFlags() + if opts.BindHost == "" { + host := os.Getenv("HD_BIND") + if host == "" { + host = "localhost" + } + opts.BindHost = host + } setupLogging(opts.Verbose) - address, webServerDone := dashboard.StartServer(version, int(opts.Port), opts.Namespace, opts.Verbose, opts.NoTracking) + server := dashboard.Server{ + Version: version, + Namespace: opts.Namespace, + Address: fmt.Sprintf("%s:%d", opts.BindHost, opts.Port), + Debug: opts.Verbose, + NoTracking: opts.NoTracking, + } + address, webServerDone := server.StartServer() if !opts.NoTracking { log.Infof("User analytics is collected to improve the quality, disable it with --no-analytics") diff --git a/pkg/dashboard/server.go b/pkg/dashboard/server.go index 2402072..56c6401 100644 --- a/pkg/dashboard/server.go +++ b/pkg/dashboard/server.go @@ -3,22 +3,31 @@ package dashboard import ( "context" "encoding/json" + "fmt" + "net/http" + "os" + "strings" + "time" + "github.com/gin-gonic/gin" "github.com/hashicorp/go-version" "github.com/komodorio/helm-dashboard/pkg/dashboard/scanners" "github.com/komodorio/helm-dashboard/pkg/dashboard/subproc" "github.com/komodorio/helm-dashboard/pkg/dashboard/utils" log "github.com/sirupsen/logrus" - "net/http" - "os" - "strconv" - "strings" - "time" ) -func StartServer(version string, port int, ns string, debug bool, noTracking bool) (string, utils.ControlChan) { +type Server struct { + Version string + Namespace string + Address string + Debug bool + NoTracking bool +} + +func (s Server) StartServer() (string, utils.ControlChan) { data := subproc.DataLayer{ - Namespace: ns, + Namespace: s.Namespace, } err := data.CheckConnectivity() if err != nil { @@ -27,37 +36,33 @@ func StartServer(version string, port int, ns string, debug bool, noTracking boo } data.StatusInfo = &subproc.StatusInfo{ - CurVer: version, - Analytics: !noTracking, - LimitedToNamespace: ns, + CurVer: s.Version, + Analytics: !s.NoTracking, + LimitedToNamespace: s.Namespace, } go checkUpgrade(data.StatusInfo) discoverScanners(&data) - address := os.Getenv("HD_BIND") - if address == "" { - address = "localhost" - } - - address += ":" + strconv.Itoa(port) - abort := make(utils.ControlChan) - api := NewRouter(abort, &data, debug) - done := startBackgroundServer(address, api, abort) + api := NewRouter(abort, &data, s.Debug) + done := s.startBackgroundServer(api, abort) - return "http://" + address, done + return "http://" + s.Address, done } -func startBackgroundServer(addr string, routes *gin.Engine, abort utils.ControlChan) utils.ControlChan { +func (s Server) startBackgroundServer(routes *gin.Engine, abort utils.ControlChan) utils.ControlChan { done := make(utils.ControlChan) - server := &http.Server{Addr: addr, Handler: routes} + server := &http.Server{ + Addr: s.Address, + Handler: routes, + } go func() { err := server.ListenAndServe() if err != nil && err != http.ErrServerClosed { - log.Warnf("Looks like port is busy for %s, checking if it's us...", addr) - if itIsUs(addr) { + log.Warnf("Looks like port is busy for %s, checking if it's us...", s.Address) + if s.itIsUs() { log.Infof("Yes, it's another instance of us. Just reuse it.") } else { panic(err) @@ -77,11 +82,14 @@ func startBackgroundServer(addr string, routes *gin.Engine, abort utils.ControlC return done } -func itIsUs(addr string) bool { - var myClient = &http.Client{Timeout: 5 * time.Second} - r, err := myClient.Get("http://" + addr + "/status") +func (s Server) itIsUs() bool { + url := fmt.Sprintf("http://%s/status", s.Address) + var myClient = &http.Client{ + Timeout: 5 * time.Second, + } + r, err := myClient.Get(url) if err != nil { - log.Debugf("It's not us on %s: %s", addr, err) + log.Debugf("It's not us on %s: %s", s.Address, err) return false } defer r.Body.Close()