From 93dac80a862ff3d4415f732e9350330538f38fa8 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Tue, 31 Dec 2013 16:45:13 -0800 Subject: [PATCH] Adding support for advertise address --- command/agent/agent.go | 32 +++++++++++++++++++++++++++++++- command/agent/command.go | 13 +++++++------ command/agent/config.go | 17 ++++++++++++----- consul/config.go | 7 +++++-- consul/server.go | 2 +- 5 files changed, 56 insertions(+), 15 deletions(-) diff --git a/command/agent/agent.go b/command/agent/agent.go index e701c37ee0..77fef1aa9b 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -6,6 +6,7 @@ import ( "github.com/hashicorp/serf/serf" "io" "log" + "net" "os" "sync" ) @@ -53,6 +54,24 @@ func Create(config *Config, logOutput io.Writer) (*Agent, error) { return nil, fmt.Errorf("Must configure a DataDir") } + // Ensure the RPC Addr is sane + if _, err := net.ResolveTCPAddr("tcp", config.ServerAddr); err != nil { + return nil, fmt.Errorf("Bad server address: %v", err) + } + + // Try to get an advertise address + if config.AdvertiseAddr != "" { + if ip := net.ParseIP(config.AdvertiseAddr); ip == nil { + return nil, fmt.Errorf("Failed to parse advertise address: %v", config.AdvertiseAddr) + } + } else { + ip, err := consul.GetPrivateIP() + if err != nil { + return nil, fmt.Errorf("Failed to get advertise address: %v", err) + } + config.AdvertiseAddr = ip.IP.String() + } + agent := &Agent{ config: config, logger: log.New(logOutput, "", log.LstdFlags), @@ -105,12 +124,23 @@ func (a *Agent) consulConfig() *consul.Config { } if a.config.SerfLanPort != 0 { base.SerfLANConfig.MemberlistConfig.BindPort = a.config.SerfLanPort + base.SerfLANConfig.MemberlistConfig.AdvertisePort = a.config.SerfLanPort } if a.config.SerfWanPort != 0 { base.SerfWANConfig.MemberlistConfig.BindPort = a.config.SerfWanPort + base.SerfWANConfig.MemberlistConfig.AdvertisePort = a.config.SerfWanPort } if a.config.ServerAddr != "" { - base.RPCAddr = a.config.ServerAddr + addr, _ := net.ResolveTCPAddr("tcp", a.config.ServerAddr) + base.RPCAddr = addr + } + if a.config.AdvertiseAddr != "" { + base.SerfLANConfig.MemberlistConfig.AdvertiseAddr = a.config.AdvertiseAddr + base.SerfWANConfig.MemberlistConfig.AdvertiseAddr = a.config.AdvertiseAddr + base.RPCAdvertise = &net.TCPAddr{ + IP: net.ParseIP(a.config.AdvertiseAddr), + Port: base.RPCAddr.Port, + } } if a.config.Bootstrap { base.Bootstrap = true diff --git a/command/agent/command.go b/command/agent/command.go index dfb2c98a2a..6493ff49c5 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -183,12 +183,13 @@ func (c *Command) Run(args []string) int { } c.Ui.Output("Consul agent running!") - c.Ui.Info(fmt.Sprintf(" Node name: '%s'", config.NodeName)) - c.Ui.Info(fmt.Sprintf("Datacenter: '%s'", config.Datacenter)) - c.Ui.Info(fmt.Sprintf(" RPC addr: '%s'", config.RPCAddr)) - c.Ui.Info(fmt.Sprintf(" HTTP addr: '%s'", config.HTTPAddr)) - c.Ui.Info(fmt.Sprintf(" Encrypted: %#v", config.EncryptKey != "")) - c.Ui.Info(fmt.Sprintf(" Server: %v", config.Server)) + c.Ui.Info(fmt.Sprintf(" Node name: '%s'", config.NodeName)) + c.Ui.Info(fmt.Sprintf(" Datacenter: '%s'", config.Datacenter)) + c.Ui.Info(fmt.Sprintf("Advertise addr: '%s'", config.AdvertiseAddr)) + c.Ui.Info(fmt.Sprintf(" RPC addr: '%s'", config.RPCAddr)) + c.Ui.Info(fmt.Sprintf(" HTTP addr: '%s'", config.HTTPAddr)) + c.Ui.Info(fmt.Sprintf(" Encrypted: %#v", config.EncryptKey != "")) + c.Ui.Info(fmt.Sprintf(" Server: %v (bootstrap: %v)", config.Server, config.Bootstrap)) // Enable log streaming c.Ui.Info("") diff --git a/command/agent/config.go b/command/agent/config.go index 345b638b10..b4910157eb 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -59,6 +59,11 @@ type Config struct { // Defaults to 0.0.0.0:8300 ServerAddr string + // AdvertiseAddr is the address we use for advertising our Serf, + // and Consul RPC IP. If not specified, the first private IP we + // find is used. + AdvertiseAddr string + // Server controls if this agent acts like a Consul server, // or merely as a client. Servers have more state, take part // in leader election, etc. @@ -81,11 +86,13 @@ type dirEnts []os.FileInfo // DefaultConfig is used to return a sane default configuration func DefaultConfig() *Config { return &Config{ - Datacenter: consul.DefaultDC, - HTTPAddr: "127.0.0.1:8500", - LogLevel: "INFO", - RPCAddr: "127.0.0.1:8400", - Server: false, + Datacenter: consul.DefaultDC, + HTTPAddr: "127.0.0.1:8500", + LogLevel: "INFO", + RPCAddr: "127.0.0.1:8400", + SerfLanPort: consul.DefaultLANSerfPort, + SerfWanPort: consul.DefaultWANSerfPort, + Server: false, } } diff --git a/consul/config.go b/consul/config.go index 551792522d..1390705b0f 100644 --- a/consul/config.go +++ b/consul/config.go @@ -11,11 +11,14 @@ import ( const ( DefaultDC = "dc1" - DefaultRPCAddr = "0.0.0.0:8300" DefaultLANSerfPort = 8301 DefaultWANSerfPort = 8302 ) +var ( + DefaultRPCAddr = &net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: 8300} +) + // Config is used to configure the server type Config struct { // Bootstrap mode is used to bring up the first Consul server. @@ -37,7 +40,7 @@ type Config struct { // RPCAddr is the RPC address used by Consul. This should be reachable // by the WAN and LAN - RPCAddr string + RPCAddr *net.TCPAddr // RPCAdvertise is the address that is advertised to other nodes for // the RPC endpoint. This can differ from the RPC address, if for example diff --git a/consul/server.go b/consul/server.go index 49b2e98edf..732f995fc4 100644 --- a/consul/server.go +++ b/consul/server.go @@ -228,7 +228,7 @@ func (s *Server) setupRPC() error { s.rpcServer.Register(&Raft{server: s}) s.rpcServer.Register(&Catalog{s}) - list, err := net.Listen("tcp", s.config.RPCAddr) + list, err := net.ListenTCP("tcp", s.config.RPCAddr) if err != nil { return err }