// New creates a Manager which has not started to accept requests yet. func New(config *Config) (*Manager, error) { dispatcherConfig := dispatcher.DefaultConfig() if config.ProtoAddr == nil { config.ProtoAddr = make(map[string]string) } if config.ProtoListener != nil && config.ProtoListener["tcp"] != nil { config.ProtoAddr["tcp"] = config.ProtoListener["tcp"].Addr().String() } // If an AdvertiseAddr was specified, we use that as our // externally-reachable address. tcpAddr := config.AdvertiseAddr if tcpAddr == "" { // Otherwise, we know we are joining an existing swarm. Use a // wildcard address to trigger remote autodetection of our // address. _, tcpAddrPort, err := net.SplitHostPort(config.ProtoAddr["tcp"]) if err != nil { return nil, fmt.Errorf("missing or invalid listen address %s", config.ProtoAddr["tcp"]) } // Even with an IPv6 listening address, it's okay to use // 0.0.0.0 here. Any "unspecified" (wildcard) IP will // be substituted with the actual source address. tcpAddr = net.JoinHostPort("0.0.0.0", tcpAddrPort) } err := os.MkdirAll(filepath.Dir(config.ProtoAddr["unix"]), 0700) if err != nil { return nil, fmt.Errorf("failed to create socket directory: %v", err) } err = os.MkdirAll(config.StateDir, 0700) if err != nil { return nil, fmt.Errorf("failed to create state directory: %v", err) } raftStateDir := filepath.Join(config.StateDir, "raft") err = os.MkdirAll(raftStateDir, 0700) if err != nil { return nil, fmt.Errorf("failed to create raft state directory: %v", err) } var listeners map[string]net.Listener if len(config.ProtoListener) > 0 { listeners = config.ProtoListener } else { listeners = make(map[string]net.Listener) for proto, addr := range config.ProtoAddr { l, err := net.Listen(proto, addr) // A unix socket may fail to bind if the file already // exists. Try replacing the file. unwrappedErr := err if op, ok := unwrappedErr.(*net.OpError); ok { unwrappedErr = op.Err } if sys, ok := unwrappedErr.(*os.SyscallError); ok { unwrappedErr = sys.Err } if proto == "unix" && unwrappedErr == syscall.EADDRINUSE { os.Remove(addr) l, err = net.Listen(proto, addr) if err != nil { return nil, err } } else if err != nil { return nil, err } listeners[proto] = l } } raftCfg := raft.DefaultNodeConfig() if config.ElectionTick > 0 { raftCfg.ElectionTick = int(config.ElectionTick) } if config.HeartbeatTick > 0 { raftCfg.HeartbeatTick = int(config.HeartbeatTick) } newNodeOpts := raft.NewNodeOptions{ ID: config.SecurityConfig.ClientTLSCreds.NodeID(), Addr: tcpAddr, JoinAddr: config.JoinRaft, Config: raftCfg, StateDir: raftStateDir, ForceNewCluster: config.ForceNewCluster, TLSCredentials: config.SecurityConfig.ClientTLSCreds, } RaftNode := raft.NewNode(context.TODO(), newNodeOpts) opts := []grpc.ServerOption{ grpc.Creds(config.SecurityConfig.ServerTLSCreds)} m := &Manager{ config: config, listeners: listeners, caserver: ca.NewServer(RaftNode.MemoryStore(), config.SecurityConfig), Dispatcher: dispatcher.New(RaftNode, dispatcherConfig), server: grpc.NewServer(opts...), localserver: grpc.NewServer(opts...), RaftNode: RaftNode, started: make(chan struct{}), stopped: make(chan struct{}), } return m, nil }
// New creates a Manager which has not started to accept requests yet. func New(config *Config) (*Manager, error) { dispatcherConfig := dispatcher.DefaultConfig() if config.ProtoAddr == nil { config.ProtoAddr = make(map[string]string) } if config.ProtoListener != nil && config.ProtoListener["tcp"] != nil { config.ProtoAddr["tcp"] = config.ProtoListener["tcp"].Addr().String() } tcpAddr := config.ProtoAddr["tcp"] if tcpAddr == "" { return nil, errors.New("no tcp listen address or listener provided") } listenHost, listenPort, err := net.SplitHostPort(tcpAddr) if err == nil { ip := net.ParseIP(listenHost) if ip != nil && ip.IsUnspecified() { // Find our local IP address associated with the default route. // This may not be the appropriate address to use for internal // cluster communications, but it seems like the best default. // The admin can override this address if necessary. conn, err := net.Dial("udp", "8.8.8.8:53") if err != nil { return nil, fmt.Errorf("could not determine local IP address: %v", err) } localAddr := conn.LocalAddr().String() conn.Close() listenHost, _, err = net.SplitHostPort(localAddr) if err != nil { return nil, fmt.Errorf("could not split local IP address: %v", err) } tcpAddr = net.JoinHostPort(listenHost, listenPort) } } // TODO(stevvooe): Reported address of manager is plumbed to listen addr // for now, may want to make this separate. This can be tricky to get right // so we need to make it easy to override. This needs to be the address // through which agent nodes access the manager. dispatcherConfig.Addr = tcpAddr err = os.MkdirAll(filepath.Dir(config.ProtoAddr["unix"]), 0700) if err != nil { return nil, fmt.Errorf("failed to create socket directory: %v", err) } err = os.MkdirAll(config.StateDir, 0700) if err != nil { return nil, fmt.Errorf("failed to create state directory: %v", err) } raftStateDir := filepath.Join(config.StateDir, "raft") err = os.MkdirAll(raftStateDir, 0700) if err != nil { return nil, fmt.Errorf("failed to create raft state directory: %v", err) } var listeners map[string]net.Listener if len(config.ProtoListener) > 0 { listeners = config.ProtoListener } else { listeners = make(map[string]net.Listener) for proto, addr := range config.ProtoAddr { l, err := net.Listen(proto, addr) // A unix socket may fail to bind if the file already // exists. Try replacing the file. unwrappedErr := err if op, ok := unwrappedErr.(*net.OpError); ok { unwrappedErr = op.Err } if sys, ok := unwrappedErr.(*os.SyscallError); ok { unwrappedErr = sys.Err } if proto == "unix" && unwrappedErr == syscall.EADDRINUSE { os.Remove(addr) l, err = net.Listen(proto, addr) if err != nil { return nil, err } } else if err != nil { return nil, err } listeners[proto] = l } } raftCfg := raft.DefaultNodeConfig() if config.ElectionTick > 0 { raftCfg.ElectionTick = int(config.ElectionTick) } if config.HeartbeatTick > 0 { raftCfg.HeartbeatTick = int(config.HeartbeatTick) } newNodeOpts := raft.NewNodeOptions{ ID: config.SecurityConfig.ClientTLSCreds.NodeID(), Addr: tcpAddr, JoinAddr: config.JoinRaft, Config: raftCfg, StateDir: raftStateDir, ForceNewCluster: config.ForceNewCluster, TLSCredentials: config.SecurityConfig.ClientTLSCreds, } RaftNode := raft.NewNode(context.TODO(), newNodeOpts) opts := []grpc.ServerOption{ grpc.Creds(config.SecurityConfig.ServerTLSCreds)} m := &Manager{ config: config, listeners: listeners, caserver: ca.NewServer(RaftNode.MemoryStore(), config.SecurityConfig), Dispatcher: dispatcher.New(RaftNode, dispatcherConfig), server: grpc.NewServer(opts...), localserver: grpc.NewServer(opts...), RaftNode: RaftNode, stopped: make(chan struct{}), } return m, nil }
// New creates a Manager which has not started to accept requests yet. func New(config *Config) (*Manager, error) { dispatcherConfig := dispatcher.DefaultConfig() if config.ProtoAddr == nil { config.ProtoAddr = make(map[string]string) } if config.ProtoListener != nil && config.ProtoListener["tcp"] != nil { config.ProtoAddr["tcp"] = config.ProtoListener["tcp"].Addr().String() } tcpAddr := config.ProtoAddr["tcp"] if config.AdvertiseAddr != "" { tcpAddr = config.AdvertiseAddr } if tcpAddr == "" { return nil, errors.New("no tcp listen address or listener provided") } dispatcherConfig.Addr = tcpAddr err := os.MkdirAll(filepath.Dir(config.ProtoAddr["unix"]), 0700) if err != nil { return nil, fmt.Errorf("failed to create socket directory: %v", err) } err = os.MkdirAll(config.StateDir, 0700) if err != nil { return nil, fmt.Errorf("failed to create state directory: %v", err) } raftStateDir := filepath.Join(config.StateDir, "raft") err = os.MkdirAll(raftStateDir, 0700) if err != nil { return nil, fmt.Errorf("failed to create raft state directory: %v", err) } var listeners map[string]net.Listener if len(config.ProtoListener) > 0 { listeners = config.ProtoListener } else { listeners = make(map[string]net.Listener) for proto, addr := range config.ProtoAddr { l, err := net.Listen(proto, addr) // A unix socket may fail to bind if the file already // exists. Try replacing the file. unwrappedErr := err if op, ok := unwrappedErr.(*net.OpError); ok { unwrappedErr = op.Err } if sys, ok := unwrappedErr.(*os.SyscallError); ok { unwrappedErr = sys.Err } if proto == "unix" && unwrappedErr == syscall.EADDRINUSE { os.Remove(addr) l, err = net.Listen(proto, addr) if err != nil { return nil, err } } else if err != nil { return nil, err } listeners[proto] = l } } raftCfg := raft.DefaultNodeConfig() if config.ElectionTick > 0 { raftCfg.ElectionTick = int(config.ElectionTick) } if config.HeartbeatTick > 0 { raftCfg.HeartbeatTick = int(config.HeartbeatTick) } newNodeOpts := raft.NewNodeOptions{ ID: config.SecurityConfig.ClientTLSCreds.NodeID(), Addr: tcpAddr, JoinAddr: config.JoinRaft, Config: raftCfg, StateDir: raftStateDir, ForceNewCluster: config.ForceNewCluster, TLSCredentials: config.SecurityConfig.ClientTLSCreds, } RaftNode := raft.NewNode(context.TODO(), newNodeOpts) opts := []grpc.ServerOption{ grpc.Creds(config.SecurityConfig.ServerTLSCreds)} m := &Manager{ config: config, listeners: listeners, caserver: ca.NewServer(RaftNode.MemoryStore(), config.SecurityConfig), Dispatcher: dispatcher.New(RaftNode, dispatcherConfig), server: grpc.NewServer(opts...), localserver: grpc.NewServer(opts...), RaftNode: RaftNode, stopped: make(chan struct{}), } return m, nil }
// New creates a Manager which has not started to accept requests yet. func New(config *Config) (*Manager, error) { dispatcherConfig := dispatcher.DefaultConfig() // If an AdvertiseAddr was specified, we use that as our // externally-reachable address. advertiseAddr := config.RemoteAPI.AdvertiseAddr var advertiseAddrPort string if advertiseAddr == "" { // Otherwise, we know we are joining an existing swarm. Use a // wildcard address to trigger remote autodetection of our // address. var err error _, advertiseAddrPort, err = net.SplitHostPort(config.RemoteAPI.ListenAddr) if err != nil { return nil, fmt.Errorf("missing or invalid listen address %s", config.RemoteAPI.ListenAddr) } // Even with an IPv6 listening address, it's okay to use // 0.0.0.0 here. Any "unspecified" (wildcard) IP will // be substituted with the actual source address. advertiseAddr = net.JoinHostPort("0.0.0.0", advertiseAddrPort) } err := os.MkdirAll(config.StateDir, 0700) if err != nil { return nil, errors.Wrap(err, "failed to create state directory") } raftStateDir := filepath.Join(config.StateDir, "raft") err = os.MkdirAll(raftStateDir, 0700) if err != nil { return nil, errors.Wrap(err, "failed to create raft state directory") } var listeners []net.Listener // don't create a socket directory if we're on windows. we used named pipe if runtime.GOOS != "windows" { err := os.MkdirAll(filepath.Dir(config.ControlAPI), 0700) if err != nil { return nil, errors.Wrap(err, "failed to create socket directory") } } l, err := xnet.ListenLocal(config.ControlAPI) // A unix socket may fail to bind if the file already // exists. Try replacing the file. if runtime.GOOS != "windows" { unwrappedErr := err if op, ok := unwrappedErr.(*net.OpError); ok { unwrappedErr = op.Err } if sys, ok := unwrappedErr.(*os.SyscallError); ok { unwrappedErr = sys.Err } if unwrappedErr == syscall.EADDRINUSE { os.Remove(config.ControlAPI) l, err = xnet.ListenLocal(config.ControlAPI) } } if err != nil { return nil, errors.Wrap(err, "failed to listen on control API address") } listeners = append(listeners, l) l, err = net.Listen("tcp", config.RemoteAPI.ListenAddr) if err != nil { return nil, errors.Wrap(err, "failed to listen on remote API address") } if advertiseAddrPort == "0" { advertiseAddr = l.Addr().String() config.RemoteAPI.ListenAddr = advertiseAddr } listeners = append(listeners, l) raftCfg := raft.DefaultNodeConfig() if config.ElectionTick > 0 { raftCfg.ElectionTick = int(config.ElectionTick) } if config.HeartbeatTick > 0 { raftCfg.HeartbeatTick = int(config.HeartbeatTick) } newNodeOpts := raft.NodeOptions{ ID: config.SecurityConfig.ClientTLSCreds.NodeID(), Addr: advertiseAddr, JoinAddr: config.JoinRaft, Config: raftCfg, StateDir: raftStateDir, ForceNewCluster: config.ForceNewCluster, TLSCredentials: config.SecurityConfig.ClientTLSCreds, } raftNode := raft.NewNode(newNodeOpts) opts := []grpc.ServerOption{ grpc.Creds(config.SecurityConfig.ServerTLSCreds)} m := &Manager{ config: config, listeners: listeners, caserver: ca.NewServer(raftNode.MemoryStore(), config.SecurityConfig), dispatcher: dispatcher.New(raftNode, dispatcherConfig), logbroker: logbroker.New(), server: grpc.NewServer(opts...), localserver: grpc.NewServer(opts...), raftNode: raftNode, started: make(chan struct{}), } return m, nil }
// New creates a Manager which has not started to accept requests yet. func New(config *Config) (*Manager, error) { err := os.MkdirAll(config.StateDir, 0700) if err != nil { return nil, errors.Wrap(err, "failed to create state directory") } raftStateDir := filepath.Join(config.StateDir, "raft") err = os.MkdirAll(raftStateDir, 0700) if err != nil { return nil, errors.Wrap(err, "failed to create raft state directory") } raftCfg := raft.DefaultNodeConfig() if config.ElectionTick > 0 { raftCfg.ElectionTick = int(config.ElectionTick) } if config.HeartbeatTick > 0 { raftCfg.HeartbeatTick = int(config.HeartbeatTick) } dekRotator, err := NewRaftDEKManager(config.SecurityConfig.KeyWriter()) if err != nil { return nil, err } newNodeOpts := raft.NodeOptions{ ID: config.SecurityConfig.ClientTLSCreds.NodeID(), JoinAddr: config.JoinRaft, Config: raftCfg, StateDir: raftStateDir, ForceNewCluster: config.ForceNewCluster, TLSCredentials: config.SecurityConfig.ClientTLSCreds, KeyRotator: dekRotator, } raftNode := raft.NewNode(newNodeOpts) opts := []grpc.ServerOption{ grpc.Creds(config.SecurityConfig.ServerTLSCreds)} m := &Manager{ config: *config, caserver: ca.NewServer(raftNode.MemoryStore(), config.SecurityConfig), dispatcher: dispatcher.New(raftNode, dispatcher.DefaultConfig()), logbroker: logbroker.New(raftNode.MemoryStore()), server: grpc.NewServer(opts...), localserver: grpc.NewServer(opts...), raftNode: raftNode, started: make(chan struct{}), dekRotator: dekRotator, remoteListener: make(chan net.Listener, 1), controlListener: make(chan net.Listener, 1), errServe: make(chan error, 2), } if config.ControlAPI != "" { m.config.ControlAPI = "" if err := m.BindControl(config.ControlAPI); err != nil { return nil, err } } if config.RemoteAPI != nil { m.config.RemoteAPI = nil // The context isn't used in this case (before (*Manager).Run). if err := m.BindRemote(context.Background(), *config.RemoteAPI); err != nil { if config.ControlAPI != "" { l := <-m.controlListener l.Close() } return nil, err } } return m, nil }