diff --git a/command/agent/command.go b/command/agent/command.go index 5b3c08a394..050be0d3c8 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -71,6 +71,7 @@ func (c *Command) readConfig() *Config { cmdFlags.StringVar(&cmdConfig.NodeName, "node", "", "node name") cmdFlags.StringVar(&cmdConfig.Datacenter, "dc", "", "node datacenter") cmdFlags.StringVar(&cmdConfig.DataDir, "data-dir", "", "path to the data directory") + cmdFlags.BoolVar(&cmdConfig.EnableUi, "ui", false, "enable the built-in web UI") cmdFlags.StringVar(&cmdConfig.UiDir, "ui-dir", "", "path to the web UI directory") cmdFlags.StringVar(&cmdConfig.PidFile, "pid-file", "", "path to file to store PID") cmdFlags.StringVar(&cmdConfig.EncryptKey, "encrypt", "", "gossip encryption key") @@ -990,6 +991,7 @@ Options: -rejoin Ignores a previous leave and attempts to rejoin the cluster. -server Switches agent to server mode. -syslog Enables logging to syslog + -ui Enables the built-in static web UI server -ui-dir=path Path to directory containing the Web UI resources -pid-file=path Path to file to store agent PID diff --git a/command/agent/config.go b/command/agent/config.go index d0c68df4c4..79836f8811 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -270,6 +270,10 @@ type Config struct { RetryIntervalWan time.Duration `mapstructure:"-" json:"-"` RetryIntervalWanRaw string `mapstructure:"retry_interval_wan"` + // EnableUi enables the statically-compiled assets for the Consul web UI and + // serves them at the default /ui/ endpoint automatically. + EnableUi bool `mapstructure:"ui"` + // UiDir is the directory containing the Web UI resources. // If provided, the UI endpoints will be enabled. UiDir string `mapstructure:"ui_dir"` @@ -1004,6 +1008,9 @@ func MergeConfig(a, b *Config) *Config { if b.Addresses.RPC != "" { result.Addresses.RPC = b.Addresses.RPC } + if b.EnableUi { + result.EnableUi = true + } if b.UiDir != "" { result.UiDir = b.UiDir } diff --git a/command/agent/config_test.go b/command/agent/config_test.go index 72af551ab2..b692d5059c 100644 --- a/command/agent/config_test.go +++ b/command/agent/config_test.go @@ -441,6 +441,17 @@ func TestDecodeConfig(t *testing.T) { t.Fatalf("bad: %#v", config) } + // Static UI server + input = `{"ui": true}` + config, err = DecodeConfig(bytes.NewReader([]byte(input))) + if err != nil { + t.Fatalf("err: %s", err) + } + + if !config.EnableUi { + t.Fatalf("bad: %#v", config) + } + // UI Dir input = `{"ui_dir": "/opt/consul-ui"}` config, err = DecodeConfig(bytes.NewReader([]byte(input))) @@ -1230,6 +1241,7 @@ func TestMergeConfig(t *testing.T) { Services: []*ServiceDefinition{nil}, StartJoin: []string{"1.1.1.1"}, StartJoinWan: []string{"1.1.1.1"}, + EnableUi: true, UiDir: "/opt/consul-ui", EnableSyslog: true, RejoinAfterLeave: true, diff --git a/command/agent/http.go b/command/agent/http.go index 4438d1f00d..d974db7c13 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -278,7 +278,7 @@ func (s *HTTPServer) registerHandlers(enableDebug bool) { // Use the custom UI dir if provided. if s.uiDir != "" { s.mux.Handle("/ui/", http.StripPrefix("/ui/", http.FileServer(http.Dir(s.uiDir)))) - } else { + } else if s.agent.config.EnableUi { s.mux.Handle("/ui/", http.StripPrefix("/ui/", http.FileServer(assetFS()))) } diff --git a/command/agent/http_test.go b/command/agent/http_test.go index 8571de3fed..1afabb0946 100644 --- a/command/agent/http_test.go +++ b/command/agent/http_test.go @@ -630,6 +630,26 @@ func TestScadaHTTP(t *testing.T) { scadaHttp.mux.HandleFunc("/debug/pprof/symbol", mockFn) } +func TestEnableWebUI(t *testing.T) { + httpTestWithConfig(t, func(s *HTTPServer) { + req, err := http.NewRequest("GET", "/ui/", nil) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Perform the request + resp := httptest.NewRecorder() + s.mux.ServeHTTP(resp, req) + + // Check the result + if resp.Code != 200 { + t.Fatalf("should handle ui") + } + }, func(c *Config) { + c.EnableUi = true + }) +} + // assertIndex tests that X-Consul-Index is set and non-zero func assertIndex(t *testing.T, resp *httptest.ResponseRecorder) { header := resp.Header().Get("X-Consul-Index")