diff --git a/internal/cmd/server.go b/internal/cmd/server.go index ea6866e..ccbd8ae 100644 --- a/internal/cmd/server.go +++ b/internal/cmd/server.go @@ -25,7 +25,6 @@ import ( "github.com/spf13/cobra" - "github.com/BBVA/kapow/internal/logger" "github.com/BBVA/kapow/internal/server" ) @@ -47,7 +46,7 @@ var ServerCmd = &cobra.Command{ sConf.ClientAuth, _ = cmd.Flags().GetBool("clientauth") sConf.ClientCaFile, _ = cmd.Flags().GetString("clientcafile") - debug, _ := cmd.Flags().GetBool("debug") + sConf.Debug, _ = cmd.Flags().GetBool("debug") // Set environment variables KAPOW_DATA_URL and KAPOW_CONTROL_URL only if they aren't set so we don't overwrite user's preferences if _, exist := os.LookupEnv("KAPOW_DATA_URL"); !exist { @@ -57,10 +56,6 @@ var ServerCmd = &cobra.Command{ os.Setenv("KAPOW_CONTROL_URL", "http://"+sConf.ControlBindAddr) } - if debug { - logger.RegisterLogger(logger.SCRIPTS, nil) - } - server.StartServer(sConf) if len(args) > 0 { @@ -83,11 +78,7 @@ var ServerCmd = &cobra.Command{ log.Printf("Done running powfile: %q\n", powfile) } - if debug { - processLogs() - } else { - select {} - } + select {} }, } @@ -123,12 +114,3 @@ func validateServerCommandArguments(cmd *cobra.Command, args []string) error { return nil } - -func processLogs() { - - for { - if !logger.ProcessMsg(logger.SCRIPTS) { - break - } - } -} diff --git a/internal/server/model/route.go b/internal/server/model/route.go index f630dce..53b9ed5 100644 --- a/internal/server/model/route.go +++ b/internal/server/model/route.go @@ -42,4 +42,6 @@ type Route struct { // Index is this route position in the server's routes list. // It is an output field, its value is ignored as input. Index int `json:"index"` + + Debug bool `json:"debug"` } diff --git a/internal/server/server.go b/internal/server/server.go index e4afe38..ea0d6ca 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -32,7 +32,8 @@ type ServerConfig struct { CertFile, ClientCaFile string - ClientAuth bool + ClientAuth, + Debug bool } // StartServer Starts one instance of each server in a goroutine and remains listening on a channel for trace events generated by them @@ -41,7 +42,7 @@ func StartServer(config ServerConfig) { wg.Add(3) go control.Run(config.ControlBindAddr, &wg) go data.Run(config.DataBindAddr, &wg) - go user.Run(config.UserBindAddr, &wg, config.CertFile, config.KeyFile, config.ClientCaFile, config.ClientAuth) + go user.Run(config.UserBindAddr, &wg, config.CertFile, config.KeyFile, config.ClientCaFile, config.ClientAuth, config.Debug) // Wait for servers signals in order to return wg.Wait() diff --git a/internal/server/user/mux/handlerbuilder.go b/internal/server/user/mux/handlerbuilder.go index 79f68a3..8c327fd 100644 --- a/internal/server/user/mux/handlerbuilder.go +++ b/internal/server/user/mux/handlerbuilder.go @@ -52,23 +52,30 @@ func handlerBuilder(route model.Route) http.Handler { data.Handlers.Add(h) defer data.Handlers.Remove(h.ID) - stdOutR, stdOutW, err := os.Pipe() - defer stdOutW.Close() - if err != nil { - log.Println(err) - return - } - stdErrR, stdErrW, err := os.Pipe() - defer stdErrW.Close() - if err != nil { - log.Println(err) - return + if route.Debug { + var stdOutR, stdOutW *os.File + stdOutR, stdOutW, err = os.Pipe() + defer stdOutW.Close() + if err != nil { + log.Println(err) + return + } + var stdErrR, stdErrW *os.File + stdErrR, stdErrW, err = os.Pipe() + defer stdErrW.Close() + if err != nil { + log.Println(err) + return + } + + go logStream(h.ID, "stdout", stdOutR) + go logStream(h.ID, "stderr", stdErrR) + + err = spawner(h, stdOutW, stdErrW) + } else { + err = spawner(h, nil, nil) } - go logStream(h.ID, "stdout", stdOutR) - go logStream(h.ID, "stderr", stdErrR) - - err = spawner(h, stdOutW, stdErrW) if err != nil { log.Println(err) diff --git a/internal/server/user/mux/handlerbuilder_test.go b/internal/server/user/mux/handlerbuilder_test.go index 35851c7..ee7b03d 100644 --- a/internal/server/user/mux/handlerbuilder_test.go +++ b/internal/server/user/mux/handlerbuilder_test.go @@ -1,3 +1,5 @@ +// +build !race + /* * Copyright 2019 Banco Bilbao Vizcaya Argentaria, S.A. * @@ -200,16 +202,16 @@ func TestHandlerBuilderRemovesHandlerWhenDone(t *testing.T) { } } -func TestHandlerBuilderLogToLogHandler(t *testing.T) { +func TestHandlerBuilderLogToLogHandlerWhenDebugIsEnabled(t *testing.T) { data.Handlers = data.New() - route := model.Route{} + route := model.Route{Debug: true} var got string logHandler = new(bytes.Buffer) spawner = func(h *model.Handler, out io.Writer, er io.Writer) error { - out.Write([]byte("this is stdout")) - er.Write([]byte("this is stderr")) + _, _ = out.Write([]byte("this is stdout")) + _, _ = er.Write([]byte("this is stderr")) return nil } @@ -229,3 +231,34 @@ func TestHandlerBuilderLogToLogHandler(t *testing.T) { t.Errorf("Stderr not preserved. Actual: %+q", got) } } + + +func TestHandlerBuilderDoesNotLogToLogHandlerWhenDebugIsDisabled(t *testing.T) { + data.Handlers = data.New() + route := model.Route{Debug: false} + + logHandler = new(bytes.Buffer) + + spawner = func(h *model.Handler, out io.Writer, er io.Writer) error { + if out != nil { + _, _ = out.Write([]byte("this is stdout")) + } + if er != nil { + _, _ = er.Write([]byte("this is stderr")) + } + + return nil + } + + handlerBuilder(route).ServeHTTP(nil, nil) + + // NOTE: logStream will write stdout and stderr contents eventually. + // We do not have any control the goroutines running logStream, thus we + // cannot use a synchronization primitive to wait for them. Sorry. + time.Sleep(1 * time.Second) + + size := logHandler.(*bytes.Buffer).Len() + if size != 0 { + t.Error("Something was logged to stderr with debug=false") + } +} diff --git a/internal/server/user/server.go b/internal/server/user/server.go index 980fac5..e8fc3d4 100644 --- a/internal/server/user/server.go +++ b/internal/server/user/server.go @@ -34,13 +34,20 @@ var Server = http.Server{ Handler: mux.New(), } +var DebugEndpoints bool + // Run finishes configuring Server and runs ListenAndServe on it -func Run(bindAddr string, wg *sync.WaitGroup, certFile, keyFile, cliCaFile string, cliAuth bool) { +func Run(bindAddr string, wg *sync.WaitGroup, certFile, keyFile, cliCaFile string, cliAuth, debug bool) { + Server = http.Server{ Addr: bindAddr, Handler: mux.New(), } + if debug { + Routes.SetDebug() + } + listener, err := net.Listen("tcp", bindAddr) if err != nil { log.Fatal(err) diff --git a/internal/server/user/state.go b/internal/server/user/state.go index ed240b5..d924cc9 100644 --- a/internal/server/user/state.go +++ b/internal/server/user/state.go @@ -27,6 +27,7 @@ import ( type safeRouteList struct { rs []model.Route m *sync.RWMutex + globalDebug bool } var Routes safeRouteList = New() @@ -38,9 +39,14 @@ func New() safeRouteList { } } +func (srl *safeRouteList) SetDebug() { + srl.globalDebug = true +} + func (srl *safeRouteList) Append(r model.Route) model.Route { srl.m.Lock() r.Index = len(srl.rs) + r.Debug = srl.globalDebug || r.Debug srl.rs = append(srl.rs, r) srl.m.Unlock()