Skip to content

Commit

Permalink
* adding cli config and config file support for specifying the serf w…
Browse files Browse the repository at this point in the history
…an and lan bind addresses

* updating documentation for serf wan and lan options
Fixes hashicorp#2007
  • Loading branch information
moofish32 committed Oct 10, 2016
1 parent eb44c4c commit 4040229
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 5 deletions.
13 changes: 9 additions & 4 deletions command/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,6 @@ func (a *Agent) consulConfig() *consul.Config {
if a.config.NodeName != "" {
base.NodeName = a.config.NodeName
}
if a.config.BindAddr != "" {
base.SerfLANConfig.MemberlistConfig.BindAddr = a.config.BindAddr
base.SerfWANConfig.MemberlistConfig.BindAddr = a.config.BindAddr
}
if a.config.Ports.SerfLan != 0 {
base.SerfLANConfig.MemberlistConfig.BindPort = a.config.Ports.SerfLan
base.SerfLANConfig.MemberlistConfig.AdvertisePort = a.config.Ports.SerfLan
Expand All @@ -286,6 +282,15 @@ func (a *Agent) consulConfig() *consul.Config {
Port: a.config.Ports.Server,
}
base.RPCAddr = bindAddr
// Set the SERF configs as a default, check later for overrides via Config
base.SerfLANConfig.MemberlistConfig.BindAddr = a.config.BindAddr
base.SerfWANConfig.MemberlistConfig.BindAddr = a.config.BindAddr
}
if a.config.SerfLanBindAddr != "" {
base.SerfLANConfig.MemberlistConfig.BindAddr = a.config.SerfLanBindAddr
}
if a.config.SerfWanBindAddr != "" {
base.SerfWANConfig.MemberlistConfig.BindAddr = a.config.SerfWanBindAddr
}
if a.config.AdvertiseAddr != "" {
base.SerfLANConfig.MemberlistConfig.AdvertiseAddr = a.config.AdvertiseAddr
Expand Down
41 changes: 41 additions & 0 deletions command/agent/agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ func nextConfig() *Config {
conf.Datacenter = "dc1"
conf.NodeName = fmt.Sprintf("Node %d", idx)
conf.BindAddr = "127.0.0.1"
conf.SerfLanBindAddr = "127.0.0.1"
conf.SerfWanBindAddr = "127.0.0.1"
conf.Ports.DNS = basePortNumber + idx + portOffsetDNS
conf.Ports.HTTP = basePortNumber + idx + portOffsetHTTP
conf.Ports.RPC = basePortNumber + idx + portOffsetRPC
Expand Down Expand Up @@ -124,6 +126,23 @@ func makeAgent(t *testing.T, conf *Config) (string, *Agent) {
return makeAgentLog(t, conf, nil)
}

func externalIp() (string, error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
fmt.Errorf("Unable to lookup network interfaces: %v", err)
return "", err
}
var extIp string
for _, a := range addrs {
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
extIp = ipnet.IP.String()
}
}
}
return extIp, nil
}

func TestAgentStartStop(t *testing.T) {
dir, agent := makeAgent(t, nextConfig())
defer os.RemoveAll(dir)
Expand Down Expand Up @@ -154,6 +173,28 @@ func TestAgent_RPCPing(t *testing.T) {
}
}

func TestAgent_CheckSerfBindAddrsSettings(t *testing.T) {
c := nextConfig()
eIp, err := externalIp()
if err != nil {
t.Fatalf("Unable to get a non-loopback IP: %v", err)
}
c.SerfLanBindAddr = eIp
c.SerfWanBindAddr = eIp
dir, agent := makeAgent(t, c)
defer os.RemoveAll(dir)
defer agent.Shutdown()

serfWanBind := agent.consulConfig().SerfWANConfig.MemberlistConfig.BindAddr
if serfWanBind == "127.0.0.1" {
t.Fatalf("SerfWanBindAddr is should be a non-loopback IP not %s", serfWanBind)
}

serfLanBind := agent.consulConfig().SerfLANConfig.MemberlistConfig.BindAddr
if serfLanBind == "127.0.0.1" {
t.Fatalf("SerfLanBindAddr is should be a non-loopback IP not %s", serfWanBind)
}
}
func TestAgent_CheckAdvertiseAddrsSettings(t *testing.T) {
c := nextConfig()
c.AdvertiseAddrs.SerfLan, _ = net.ResolveTCPAddr("tcp", "127.0.0.42:1233")
Expand Down
2 changes: 2 additions & 0 deletions command/agent/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ func (c *Command) readConfig() *Config {

cmdFlags.StringVar(&cmdConfig.ClientAddr, "client", "", "address to bind client listeners to (DNS, HTTP, HTTPS, RPC)")
cmdFlags.StringVar(&cmdConfig.BindAddr, "bind", "", "address to bind server listeners to")
cmdFlags.StringVar(&cmdConfig.SerfWanBindAddr, "serf-wan-bind", "", "address to bind serf wan listeners to")
cmdFlags.StringVar(&cmdConfig.SerfLanBindAddr, "serf-lan-bind", "", "address to bind serf lan listeners to")
cmdFlags.IntVar(&cmdConfig.Ports.HTTP, "http-port", 0, "http port to use")
cmdFlags.IntVar(&cmdConfig.Ports.DNS, "dns-port", 0, "DNS port to use")
cmdFlags.StringVar(&cmdConfig.AdvertiseAddr, "advertise", "", "address to advertise instead of bind addr")
Expand Down
8 changes: 8 additions & 0 deletions command/agent/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ func TestReadCliConfig(t *testing.T) {
"-data-dir", tmpDir,
"-node", `"a"`,
"-advertise-wan", "1.2.3.4",
"-serf-wan-bind", "4.3.2.1",
"-serf-lan-bind", "4.3.2.1",
},
ShutdownCh: shutdownCh,
Ui: new(cli.MockUi),
Expand All @@ -135,6 +137,12 @@ func TestReadCliConfig(t *testing.T) {
if config.AdvertiseAddrWan != "1.2.3.4" {
t.Fatalf("expected -advertise-addr-wan 1.2.3.4 got %s", config.AdvertiseAddrWan)
}
if config.SerfWanBindAddr != "4.3.2.1" {
t.Fatalf("expected -serf-wan-bind 4.3.2.1 got %s", config.SerfWanBindAddr)
}
if config.SerfLanBindAddr != "4.3.2.1" {
t.Fatalf("expected -serf-lan-bind 4.3.2.1 got %s", config.SerfLanBindAddr)
}
}

// Test LeaveOnTerm and SkipLeaveOnInt defaults for server mode
Expand Down
18 changes: 18 additions & 0 deletions command/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,18 @@ type Config struct {
// services (Gossip, Server RPC)
BindAddr string `mapstructure:"bind_addr"`

// SerfWanBindAddr is used to control the address we bind to.
// If not specified, the first private IP we find is used.
// This controls the address we use for cluster facing
// services (Gossip) Serf
SerfWanBindAddr string `mapstructure:"serf_wan_bind"`

// SerfLanBindAddr is used to control the address we bind to.
// If not specified, the first private IP we find is used.
// This controls the address we use for cluster facing
// services (Gossip) Serf
SerfLanBindAddr string `mapstructure:"serf_lan_bind"`

// AdvertiseAddr is the address we use for advertising our Serf,
// and Consul RPC IP. If not specified, bind address is used.
AdvertiseAddr string `mapstructure:"advertise_addr"`
Expand Down Expand Up @@ -1163,6 +1175,12 @@ func MergeConfig(a, b *Config) *Config {
if b.AdvertiseAddrWan != "" {
result.AdvertiseAddrWan = b.AdvertiseAddrWan
}
if b.SerfWanBindAddr != "" {
result.SerfWanBindAddr = b.SerfWanBindAddr
}
if b.SerfLanBindAddr != "" {
result.SerfLanBindAddr = b.SerfLanBindAddr
}
if b.TranslateWanAddrs == true {
result.TranslateWanAddrs = true
}
Expand Down
11 changes: 10 additions & 1 deletion command/agent/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,9 @@ func TestDecodeConfig(t *testing.T) {
}

// Server addrs
input = `{"ports": {"server": 8000}, "bind_addr": "127.0.0.2", "advertise_addr": "127.0.0.3"}`
input = `{"ports": {"server": 8000}, "bind_addr": "127.0.0.2", "advertise_addr": "127.0.0.3", "serf_lan_bind": "127.0.0.4", "serf_wan_bind": "52.54.55.56"}`
config, err = DecodeConfig(bytes.NewReader([]byte(input)))

if err != nil {
t.Fatalf("err: %s", err)
}
Expand All @@ -189,6 +190,14 @@ func TestDecodeConfig(t *testing.T) {
t.Fatalf("bad: %#v", config)
}

if config.SerfWanBindAddr != "52.54.55.56" {
t.Fatalf("bad: %#v", config)
}

if config.SerfLanBindAddr != "127.0.0.4" {
t.Fatalf("bad: %#v", config)
}

if config.AdvertiseAddr != "127.0.0.3" {
t.Fatalf("bad: %#v", config)
}
Expand Down
13 changes: 13 additions & 0 deletions website/source/docs/agent/options.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ will exit with an error at startup.
Consul uses both TCP and UDP and the same port for both. If you
have any firewalls, be sure to allow both protocols.

* <a name="_serf_wan_bind"></a><a href="#_serf_wan_bind">`-serf-wan-bind`</a> - The address that should be bound to for Serf WAN gossip communications.
By default, the value follows the same rules as [`-bind` command-line flag](#_bind)

* <a name="_serf_lan_bind"></a><a href="#_serf_lan_bind">`-serf-lan-bind`</a> - The address that should be bound to for Serf LAN gossip communications.
This is an IP address that should be reachable by all other LAN nodes in the cluster.
By default, the value follows the same rules as [`-bind` command-line flag](#_bind)

* <a name="_client"></a><a href="#_client">`-client`</a> - The address to which
Consul will bind client interfaces,
including the HTTP, DNS, and RPC servers. By default, this is "127.0.0.1",
Expand Down Expand Up @@ -407,6 +414,12 @@ Consul will not enable TLS for the HTTP API unless the `https` port has been ass
* <a name="advertise_addr"></a><a href="#advertise_addr">`advertise_addr`</a> Equivalent to
the [`-advertise` command-line flag](#_advertise).

* <a name="serf_wan_bind"></a><a href="#serf_wan_bind">`serf_wan_bind`</a> Equivalent to
the [`-serf-wan-bind` command-line flag](#_serf_wan_bind).

* <a name="serf_lan_bind"></a><a href="#serf_lan_bind">`serf_lan_bind`</a> Equivalent to
the [`-serf-lan-bind` command-line flag](#_serf_lan_bind).

* <a name="advertise_addrs"></a><a href="#advertise_addrs">`advertise_addrs`</a> Allows to set
the advertised addresses for SerfLan, SerfWan and RPC together with the port. This gives
you more control than <a href="#_advertise">`-advertise`</a> or <a href="#_advertise-wan">`-advertise-wan`</a>
Expand Down

0 comments on commit 4040229

Please sign in to comment.