mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #16769 from LK4D4/fix_volume_socket
Allocate resources for server API before daemon creation
This commit is contained in:
commit
80f2e3f0c6
5 changed files with 56 additions and 47 deletions
|
@ -2,7 +2,6 @@ package server
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -28,22 +27,39 @@ type Config struct {
|
|||
Version string
|
||||
SocketGroup string
|
||||
TLSConfig *tls.Config
|
||||
Addrs []Addr
|
||||
}
|
||||
|
||||
// Server contains instance details for the server
|
||||
type Server struct {
|
||||
cfg *Config
|
||||
start chan struct{}
|
||||
servers []serverCloser
|
||||
servers []*HTTPServer
|
||||
routers []router.Router
|
||||
}
|
||||
|
||||
// Addr contains string representation of address and its protocol (tcp, unix...).
|
||||
type Addr struct {
|
||||
Proto string
|
||||
Addr string
|
||||
}
|
||||
|
||||
// New returns a new instance of the server based on the specified configuration.
|
||||
func New(cfg *Config) *Server {
|
||||
return &Server{
|
||||
// It allocates resources which will be needed for ServeAPI(ports, unix-sockets).
|
||||
func New(cfg *Config) (*Server, error) {
|
||||
s := &Server{
|
||||
cfg: cfg,
|
||||
start: make(chan struct{}),
|
||||
}
|
||||
for _, addr := range cfg.Addrs {
|
||||
srv, err := s.newServer(addr.Proto, addr.Addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logrus.Debugf("Server created for HTTP on %s (%s)", addr.Proto, addr.Addr)
|
||||
s.servers = append(s.servers, srv...)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Close closes servers and thus stop receiving requests
|
||||
|
@ -55,39 +71,23 @@ func (s *Server) Close() {
|
|||
}
|
||||
}
|
||||
|
||||
type serverCloser interface {
|
||||
Serve() error
|
||||
Close() error
|
||||
}
|
||||
|
||||
// ServeAPI loops through all of the protocols sent in to docker and spawns
|
||||
// off a go routine to setup a serving http.Server for each.
|
||||
func (s *Server) ServeAPI(protoAddrs []string) error {
|
||||
var chErrors = make(chan error, len(protoAddrs))
|
||||
|
||||
for _, protoAddr := range protoAddrs {
|
||||
protoAddrParts := strings.SplitN(protoAddr, "://", 2)
|
||||
if len(protoAddrParts) != 2 {
|
||||
return fmt.Errorf("bad format, expected PROTO://ADDR")
|
||||
}
|
||||
srv, err := s.newServer(protoAddrParts[0], protoAddrParts[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.servers = append(s.servers, srv...)
|
||||
|
||||
for _, s := range srv {
|
||||
logrus.Infof("Listening for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1])
|
||||
go func(s serverCloser) {
|
||||
if err := s.Serve(); err != nil && strings.Contains(err.Error(), "use of closed network connection") {
|
||||
err = nil
|
||||
}
|
||||
chErrors <- err
|
||||
}(s)
|
||||
}
|
||||
// ServeAPI loops through all initialized servers and spawns goroutine
|
||||
// with Server method for each. It sets CreateMux() as Handler also.
|
||||
func (s *Server) ServeAPI() error {
|
||||
var chErrors = make(chan error, len(s.servers))
|
||||
for _, srv := range s.servers {
|
||||
srv.srv.Handler = s.CreateMux()
|
||||
go func(srv *HTTPServer) {
|
||||
var err error
|
||||
logrus.Errorf("API listen on %s", srv.l.Addr())
|
||||
if err = srv.Serve(); err != nil && strings.Contains(err.Error(), "use of closed network connection") {
|
||||
err = nil
|
||||
}
|
||||
chErrors <- err
|
||||
}(srv)
|
||||
}
|
||||
|
||||
for i := 0; i < len(protoAddrs); i++ {
|
||||
for i := 0; i < len(s.servers); i++ {
|
||||
err := <-chErrors
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -14,8 +14,9 @@ import (
|
|||
systemdActivation "github.com/coreos/go-systemd/activation"
|
||||
)
|
||||
|
||||
// newServer sets up the required serverClosers and does protocol specific checking.
|
||||
func (s *Server) newServer(proto, addr string) ([]serverCloser, error) {
|
||||
// newServer sets up the required HTTPServers and does protocol specific checking.
|
||||
// newServer does not set any muxers, you should set it later to Handler field
|
||||
func (s *Server) newServer(proto, addr string) ([]*HTTPServer, error) {
|
||||
var (
|
||||
err error
|
||||
ls []net.Listener
|
||||
|
@ -45,12 +46,11 @@ func (s *Server) newServer(proto, addr string) ([]serverCloser, error) {
|
|||
default:
|
||||
return nil, fmt.Errorf("Invalid protocol format: %q", proto)
|
||||
}
|
||||
var res []serverCloser
|
||||
var res []*HTTPServer
|
||||
for _, l := range ls {
|
||||
res = append(res, &HTTPServer{
|
||||
&http.Server{
|
||||
Addr: addr,
|
||||
Handler: s.CreateMux(),
|
||||
Addr: addr,
|
||||
},
|
||||
l,
|
||||
})
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
// NewServer sets up the required Server and does protocol specific checking.
|
||||
func (s *Server) newServer(proto, addr string) ([]serverCloser, error) {
|
||||
func (s *Server) newServer(proto, addr string) ([]*HTTPServer, error) {
|
||||
var (
|
||||
ls []net.Listener
|
||||
)
|
||||
|
@ -25,12 +25,11 @@ func (s *Server) newServer(proto, addr string) ([]serverCloser, error) {
|
|||
return nil, errors.New("Invalid protocol format. Windows only supports tcp.")
|
||||
}
|
||||
|
||||
var res []serverCloser
|
||||
var res []*HTTPServer
|
||||
for _, l := range ls {
|
||||
res = append(res, &HTTPServer{
|
||||
&http.Server{
|
||||
Addr: addr,
|
||||
Handler: s.CreateMux(),
|
||||
Addr: addr,
|
||||
},
|
||||
l,
|
||||
})
|
||||
|
|
|
@ -223,6 +223,17 @@ func (cli *DaemonCli) CmdDaemon(args ...string) error {
|
|||
}
|
||||
serverConfig.TLSConfig = tlsConfig
|
||||
}
|
||||
for _, protoAddr := range commonFlags.Hosts {
|
||||
protoAddrParts := strings.SplitN(protoAddr, "://", 2)
|
||||
if len(protoAddrParts) != 2 {
|
||||
logrus.Fatalf("bad format %s, expected PROTO://ADDR", protoAddr)
|
||||
}
|
||||
serverConfig.Addrs = append(serverConfig.Addrs, apiserver.Addr{Proto: protoAddrParts[0], Addr: protoAddrParts[1]})
|
||||
}
|
||||
api, err := apiserver.New(serverConfig)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
if err := migrateKey(); err != nil {
|
||||
logrus.Fatal(err)
|
||||
|
@ -249,7 +260,6 @@ func (cli *DaemonCli) CmdDaemon(args ...string) error {
|
|||
"graphdriver": d.GraphDriver().String(),
|
||||
}).Info("Docker daemon")
|
||||
|
||||
api := apiserver.New(serverConfig)
|
||||
api.InitRouters(d)
|
||||
|
||||
// The serve API routine never exits unless an error occurs
|
||||
|
@ -257,7 +267,7 @@ func (cli *DaemonCli) CmdDaemon(args ...string) error {
|
|||
// daemon doesn't exit
|
||||
serveAPIWait := make(chan error)
|
||||
go func() {
|
||||
if err := api.ServeAPI(commonFlags.Hosts); err != nil {
|
||||
if err := api.ServeAPI(); err != nil {
|
||||
logrus.Errorf("ServeAPI error: %v", err)
|
||||
serveAPIWait <- err
|
||||
return
|
||||
|
|
|
@ -1462,7 +1462,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *check.C) {
|
|||
|
||||
socket := filepath.Join(s.d.folder, "docker.sock")
|
||||
|
||||
out, err := s.d.Cmd("run", "-d", "-v", socket+":/sock", "busybox")
|
||||
out, err := s.d.Cmd("run", "-d", "--restart=always", "-v", socket+":/sock", "busybox")
|
||||
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
||||
c.Assert(s.d.Restart(), check.IsNil)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue