diff --git a/admin/admin.go b/admin/admin.go index 36101a5d5d..e95e7dfb59 100644 --- a/admin/admin.go +++ b/admin/admin.go @@ -1,6 +1,7 @@ package admin import ( + "log" "net" "net/http" "strings" @@ -13,45 +14,48 @@ import ( // Server manages InfluxDB's admin web server. type Server struct { - port string + addr string listener net.Listener closed bool } -// NewServer constructs a new admin web server. The "port" argument should be a -// string that looks like ":8083" or whatever port to serve on. -func NewServer(port string) *Server { - return &Server{port: port, closed: true} +// NewServer constructs a new admin web server. The "addr" argument should be a +// string that looks like ":8083" or whatever addr to serve on. +func NewServer(addr string) *Server { + return &Server{addr: addr, closed: true} } // ListenAndServe starts the admin web server and serves requests until // s.Close() is called. -func (s *Server) ListenAndServe() { - if s.port == "" { - return +func (s *Server) ListenAndServe() error { + if s.addr == "" { + return nil } var err error - s.listener, err = net.Listen("tcp", s.port) + s.listener, err = net.Listen("tcp", s.addr) if err != nil { - return + return err } s.closed = false statikFS, _ := fs.New() - err = http.Serve(s.listener, http.FileServer(statikFS)) - if !strings.Contains(err.Error(), "closed") { - panic(err) - } + go func() { + err = http.Serve(s.listener, http.FileServer(statikFS)) + if !strings.Contains(err.Error(), "closed") { + log.Fatalf("admin server failed to server on %s: %s", s.addr, err) + } + }() + return err } // Close stops the admin web server. -func (s *Server) Close() { +func (s *Server) Close() error { if s.closed { - return + return nil } s.closed = true - s.listener.Close() + return s.listener.Close() } diff --git a/cmd/influxd/run.go b/cmd/influxd/run.go index 858800e998..62d8e1b1c3 100644 --- a/cmd/influxd/run.go +++ b/cmd/influxd/run.go @@ -46,6 +46,7 @@ type Node struct { DataNode *influxdb.Server raftLog *raft.Log + adminServer *admin.Server clusterListener net.Listener // The cluster TCP listener } @@ -54,6 +55,10 @@ func (s *Node) Close() { log.Fatalf("error closing cluster listener: %s", err) } + if err := s.closeAdminServer(); err != nil { + log.Fatalf("error closing admin server: %s", err) + } + if s.DataNode != nil { if err := s.DataNode.Close(); err != nil { log.Fatalf("error data broker: %s", err) @@ -73,6 +78,20 @@ func (s *Node) Close() { } } +func (s *Node) openAdminServer(port int) error { + // Start the admin interface on the default port + addr := net.JoinHostPort("", strconv.Itoa(port)) + s.adminServer = admin.NewServer(addr) + return s.adminServer.ListenAndServe() +} + +func (s *Node) closeAdminServer() error { + if s.adminServer != nil { + return s.adminServer.Close() + } + return nil +} + func (s *Node) openClusterListener(addr string, h http.Handler) error { var err error // We want to make sure we are spun up before we exit this function, so we manually listen and serve @@ -256,12 +275,11 @@ func (cmd *RunCommand) Open(config *Config, join string) *Node { log.Println("snapshot endpoint disabled") } - // Start the admin interface on the default port if cmd.config.Admin.Enabled { - port := fmt.Sprintf(":%d", cmd.config.Admin.Port) - log.Printf("starting admin server on %s", port) - a := admin.NewServer(port) - go a.ListenAndServe() + if err := cmd.node.openAdminServer(cmd.config.Admin.Port); err != nil { + log.Fatalf("admin server failed to listen on :%d: %s", cmd.config.Admin.Port, err) + } + log.Printf("admin server listening on :%d", cmd.config.Admin.Port) } // Spin up the collectd server