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