Implement advertise_addrs for SerfLan, SerfWan and RPC.

Fixes #550.
This will make it possible to configure the advertised adresses for
SerfLan, SerfWan and RPC. It will enable multiple consul clients on a
single host which is very useful in a container environment.

This option might override advertise_addr and advertise_addr_wan
depending on the configuration.

It will be configureable with advertise_addrs. Example:

{
  "advertise_addrs": {
    "serf_lan": "10.0.120.91:4424",
    "serf_wan": "201.20.10.61:4423",
    "rpc": "10.20.10.61:4424"
  }
}
This commit is contained in:
Hans Hasselberg 2015-06-05 13:44:42 +02:00
parent 7e82b3c32c
commit 4598087df3
5 changed files with 149 additions and 0 deletions

View File

@ -244,6 +244,17 @@ func (a *Agent) consulConfig() *consul.Config {
Port: a.config.Ports.Server,
}
}
if a.config.AdvertiseAddrs.SerfLan != nil {
base.SerfLANConfig.MemberlistConfig.AdvertiseAddr = a.config.AdvertiseAddrs.SerfLan.IP.String()
base.SerfLANConfig.MemberlistConfig.AdvertisePort = a.config.AdvertiseAddrs.SerfLan.Port
}
if a.config.AdvertiseAddrs.SerfWan != nil {
base.SerfWANConfig.MemberlistConfig.AdvertiseAddr = a.config.AdvertiseAddrs.SerfWan.IP.String()
base.SerfWANConfig.MemberlistConfig.AdvertisePort = a.config.AdvertiseAddrs.SerfWan.Port
}
if a.config.AdvertiseAddrs.RPC != nil {
base.RPCAdvertise = a.config.AdvertiseAddrs.RPC
}
if a.config.Bootstrap {
base.Bootstrap = true
}

View File

@ -6,6 +6,7 @@ import (
"fmt"
"io"
"io/ioutil"
"net"
"os"
"path/filepath"
"reflect"
@ -134,6 +135,37 @@ func TestAgent_RPCPing(t *testing.T) {
}
}
func TestAgent_CheckAdvertiseAddrsSettings(t *testing.T) {
c := nextConfig()
c.AdvertiseAddrs.SerfLan, _ = net.ResolveTCPAddr("tcp", "127.0.0.42:1233")
c.AdvertiseAddrs.SerfWan, _ = net.ResolveTCPAddr("tcp", "127.0.0.43:1234")
c.AdvertiseAddrs.RPC, _ = net.ResolveTCPAddr("tcp", "127.0.0.44:1235")
dir, agent := makeAgent(t, c)
defer os.RemoveAll(dir)
defer agent.Shutdown()
serfLanAddr := agent.consulConfig().SerfLANConfig.MemberlistConfig.AdvertiseAddr
if serfLanAddr != "127.0.0.42" {
t.Fatalf("SerfLan is not properly set to '127.0.0.42': %s", serfLanAddr)
}
serfLanPort := agent.consulConfig().SerfLANConfig.MemberlistConfig.AdvertisePort
if serfLanPort != 1233 {
t.Fatalf("SerfLan is not properly set to '1233': %s", serfLanPort)
}
serfWanAddr := agent.consulConfig().SerfWANConfig.MemberlistConfig.AdvertiseAddr
if serfWanAddr != "127.0.0.43" {
t.Fatalf("SerfWan is not properly set to '127.0.0.43': %s", serfWanAddr)
}
serfWanPort := agent.consulConfig().SerfWANConfig.MemberlistConfig.AdvertisePort
if serfWanPort != 1234 {
t.Fatalf("SerfWan is not properly set to '1234': %s", serfWanPort)
}
rpc := agent.consulConfig().RPCAdvertise
if rpc != c.AdvertiseAddrs.RPC {
t.Fatalf("RPC is not properly set to %v: %s", c.AdvertiseAddrs.RPC, rpc)
}
}
func TestAgent_AddService(t *testing.T) {
dir, agent := makeAgent(t, nextConfig())
defer os.RemoveAll(dir)

View File

@ -40,6 +40,15 @@ type AddressConfig struct {
RPC string // CLI RPC
}
type AdvertiseAddrsConfig struct {
SerfLan *net.TCPAddr `mapstructure:"-"`
SerfLanRaw string `mapstructure:"serf_lan"`
SerfWan *net.TCPAddr `mapstructure:"-"`
SerfWanRaw string `mapstructure:"serf_wan"`
RPC *net.TCPAddr `mapstructure:"-"`
RPCRaw string `mapstructure:"rpc"`
}
// DNSConfig is used to fine tune the DNS sub-system.
// It can be used to control cache values, and stale
// reads
@ -142,6 +151,9 @@ type Config struct {
// and Consul RPC IP. If not specified, bind address is used.
AdvertiseAddr string `mapstructure:"advertise_addr"`
// AdvertiseAddrs configuration
AdvertiseAddrs AdvertiseAddrsConfig `mapstructure:"advertise_addrs"`
// AdvertiseAddrWan is the address we use for advertising our
// Serf WAN IP. If not specified, the general advertise address is used.
AdvertiseAddrWan string `mapstructure:"advertise_addr_wan"`
@ -638,6 +650,30 @@ func DecodeConfig(r io.Reader) (*Config, error) {
result.SessionTTLMin = dur
}
if result.AdvertiseAddrs.SerfLanRaw != "" {
addr, err := net.ResolveTCPAddr("tcp", result.AdvertiseAddrs.SerfLanRaw)
if err != nil {
return nil, fmt.Errorf("AdvertiseAddrs.SerfLan is invalid: %v", err)
}
result.AdvertiseAddrs.SerfLan = addr
}
if result.AdvertiseAddrs.SerfWanRaw != "" {
addr, err := net.ResolveTCPAddr("tcp", result.AdvertiseAddrs.SerfWanRaw)
if err != nil {
return nil, fmt.Errorf("AdvertiseAddrs.SerfWan is invalid: %v", err)
}
result.AdvertiseAddrs.SerfWan = addr
}
if result.AdvertiseAddrs.RPCRaw != "" {
addr, err := net.ResolveTCPAddr("tcp", result.AdvertiseAddrs.RPCRaw)
if err != nil {
return nil, fmt.Errorf("AdvertiseAddrs.RPC is invalid: %v", err)
}
result.AdvertiseAddrs.RPC = addr
}
return &result, nil
}
@ -819,6 +855,18 @@ func MergeConfig(a, b *Config) *Config {
if b.AdvertiseAddrWan != "" {
result.AdvertiseAddrWan = b.AdvertiseAddrWan
}
if b.AdvertiseAddrs.SerfLan != nil {
result.AdvertiseAddrs.SerfLan = b.AdvertiseAddrs.SerfLan
result.AdvertiseAddrs.SerfLanRaw = b.AdvertiseAddrs.SerfLanRaw
}
if b.AdvertiseAddrs.SerfWan != nil {
result.AdvertiseAddrs.SerfWan = b.AdvertiseAddrs.SerfWan
result.AdvertiseAddrs.SerfWanRaw = b.AdvertiseAddrs.SerfWanRaw
}
if b.AdvertiseAddrs.RPC != nil {
result.AdvertiseAddrs.RPC = b.AdvertiseAddrs.RPC
result.AdvertiseAddrs.RPCRaw = b.AdvertiseAddrs.RPCRaw
}
if b.Server == true {
result.Server = b.Server
}

View File

@ -4,6 +4,7 @@ import (
"bytes"
"encoding/base64"
"io/ioutil"
"net"
"os"
"path/filepath"
"reflect"
@ -211,6 +212,45 @@ func TestDecodeConfig(t *testing.T) {
t.Fatalf("bad: %#v", config)
}
// Advertise addresses for serflan
input = `{"advertise_addrs": {"serf_lan": "127.0.0.5:1234"}}`
config, err = DecodeConfig(bytes.NewReader([]byte(input)))
if err != nil {
t.Fatalf("err: %s", err)
}
if config.AdvertiseAddrs.SerfLanRaw != "127.0.0.5:1234" {
t.Fatalf("bad: %#v", config)
}
if config.AdvertiseAddrs.SerfLan.String() != "127.0.0.5:1234" {
t.Fatalf("bad: %#v", config)
}
// Advertise addresses for serfwan
input = `{"advertise_addrs": {"serf_wan": "127.0.0.5:1234"}}`
config, err = DecodeConfig(bytes.NewReader([]byte(input)))
if err != nil {
t.Fatalf("err: %s", err)
}
if config.AdvertiseAddrs.SerfWanRaw != "127.0.0.5:1234" {
t.Fatalf("bad: %#v", config)
}
if config.AdvertiseAddrs.SerfWan.String() != "127.0.0.5:1234" {
t.Fatalf("bad: %#v", config)
}
// Advertise addresses for rpc
input = `{"advertise_addrs": {"rpc": "127.0.0.5:1234"}}`
config, err = DecodeConfig(bytes.NewReader([]byte(input)))
if err != nil {
t.Fatalf("err: %s", err)
}
if config.AdvertiseAddrs.RPCRaw != "127.0.0.5:1234" {
t.Fatalf("bad: %#v", config)
}
if config.AdvertiseAddrs.RPC.String() != "127.0.0.5:1234" {
t.Fatalf("bad: %#v", config)
}
// leave_on_terminate
input = `{"leave_on_terminate": true}`
config, err = DecodeConfig(bytes.NewReader([]byte(input)))
@ -1166,6 +1206,14 @@ func TestMergeConfig(t *testing.T) {
AtlasJoin: true,
SessionTTLMinRaw: "1000s",
SessionTTLMin: 1000 * time.Second,
AdvertiseAddrs: AdvertiseAddrsConfig{
SerfLan: &net.TCPAddr{},
SerfLanRaw: "127.0.0.5:1231",
SerfWan: &net.TCPAddr{},
SerfWanRaw: "127.0.0.5:1232",
RPC: &net.TCPAddr{},
RPCRaw: "127.0.0.5:1233",
},
}
c := MergeConfig(a, b)

View File

@ -322,6 +322,16 @@ definitions support being updated during a reload.
* <a name="advertise_addr"></a><a href="#advertise_addr">`advertise_addr`</a> Equivalent to
the [`-advertise` command-line flag](#_advertise).
* <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 (#_advertise) or (#_advertise-wan) while it serves the same purpose.
These settings might override (#_advertise) and (#_advertise-wan).
<br><br>
This is a nested setting that allows the following keys:
* `serf_lan` - The SerfLan address. Accepts values in the form of "host:port" like "10.23.31.101:8301".
* `serf_wan` - The SerfWan address. Accepts values in the form of "host:port" like "10.23.31.101:8302".
* `rpc` - The RPC address. Accepts values in the form of "host:port" like "10.23.31.101:8400".
* <a name="advertise_addr_wan"></a><a href="#advertise_addr_wan">`advertise_addr_wan`</a> Equivalent to
the [`-advertise-wan` command-line flag](#_advertise-wan).