Addresses are just addresses - no ports
Store address+port in an unexported field for ease-of-use
This commit is contained in:
parent
23de99b1df
commit
a75e5b5803
|
@ -131,13 +131,13 @@ func (a *Agent) serverConfig() (*nomad.Config, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the bind addresses
|
// Set up the bind addresses
|
||||||
rpcAddr, err := net.ResolveTCPAddr("tcp", a.config.Addresses.RPC)
|
rpcAddr, err := net.ResolveTCPAddr("tcp", a.config.normalizedAddrs.RPC)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to parse RPC address %q: %v", a.config.Addresses.RPC, err)
|
return nil, fmt.Errorf("Failed to parse RPC address %q: %v", a.config.normalizedAddrs.RPC, err)
|
||||||
}
|
}
|
||||||
serfAddr, err := net.ResolveTCPAddr("tcp", a.config.Addresses.Serf)
|
serfAddr, err := net.ResolveTCPAddr("tcp", a.config.normalizedAddrs.Serf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to parse Serf address %q: %v", a.config.Addresses.Serf, err)
|
return nil, fmt.Errorf("Failed to parse Serf address %q: %v", a.config.normalizedAddrs.Serf, err)
|
||||||
}
|
}
|
||||||
conf.RPCAddr.Port = rpcAddr.Port
|
conf.RPCAddr.Port = rpcAddr.Port
|
||||||
conf.RPCAddr.IP = rpcAddr.IP
|
conf.RPCAddr.IP = rpcAddr.IP
|
||||||
|
@ -256,7 +256,7 @@ func (a *Agent) clientConfig() (*clientconfig.Config, error) {
|
||||||
conf.Node.NodeClass = a.config.Client.NodeClass
|
conf.Node.NodeClass = a.config.Client.NodeClass
|
||||||
|
|
||||||
// Set up the HTTP advertise address
|
// Set up the HTTP advertise address
|
||||||
conf.Node.HTTPAddr = a.config.Addresses.HTTP
|
conf.Node.HTTPAddr = a.config.AdvertiseAddrs.HTTP
|
||||||
|
|
||||||
// Reserve resources on the node.
|
// Reserve resources on the node.
|
||||||
r := conf.Node.Reserved
|
r := conf.Node.Reserved
|
||||||
|
@ -315,9 +315,9 @@ func (a *Agent) setupServer() error {
|
||||||
a.server = server
|
a.server = server
|
||||||
|
|
||||||
// Consul check addresses default to bind but can be toggled to use advertise
|
// Consul check addresses default to bind but can be toggled to use advertise
|
||||||
httpCheckAddr := a.config.Addresses.HTTP
|
httpCheckAddr := a.config.normalizedAddrs.HTTP
|
||||||
rpcCheckAddr := a.config.Addresses.RPC
|
rpcCheckAddr := a.config.normalizedAddrs.RPC
|
||||||
serfCheckAddr := a.config.Addresses.Serf
|
serfCheckAddr := a.config.normalizedAddrs.Serf
|
||||||
if a.config.Consul.ChecksUseAdvertise {
|
if a.config.Consul.ChecksUseAdvertise {
|
||||||
httpCheckAddr = a.config.AdvertiseAddrs.HTTP
|
httpCheckAddr = a.config.AdvertiseAddrs.HTTP
|
||||||
rpcCheckAddr = a.config.AdvertiseAddrs.RPC
|
rpcCheckAddr = a.config.AdvertiseAddrs.RPC
|
||||||
|
@ -438,7 +438,7 @@ func (a *Agent) setupClient() error {
|
||||||
a.client = client
|
a.client = client
|
||||||
|
|
||||||
// Resolve the http check address
|
// Resolve the http check address
|
||||||
httpCheckAddr := a.config.Addresses.HTTP
|
httpCheckAddr := a.config.normalizedAddrs.HTTP
|
||||||
if a.config.Consul.ChecksUseAdvertise {
|
if a.config.Consul.ChecksUseAdvertise {
|
||||||
httpCheckAddr = a.config.AdvertiseAddrs.HTTP
|
httpCheckAddr = a.config.AdvertiseAddrs.HTTP
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,6 @@ import (
|
||||||
sconfig "github.com/hashicorp/nomad/nomad/structs/config"
|
sconfig "github.com/hashicorp/nomad/nomad/structs/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getTestLogger returns a log func appropriate for passing to
|
|
||||||
// Config.normalize()
|
|
||||||
func getTestLogger(t testing.TB) func(string) {
|
|
||||||
return func(s string) {
|
|
||||||
t.Log(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPort() int {
|
func getPort() int {
|
||||||
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
|
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -80,8 +72,8 @@ func makeAgent(t testing.TB, cb func(*Config)) (string, *Agent) {
|
||||||
cb(conf)
|
cb(conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok := conf.normalize(getTestLogger(t), config.DevMode); !ok {
|
if err := conf.normalizeAddrs(); err != nil {
|
||||||
t.Fatalf("error normalizing config")
|
t.Fatalf("error normalizing config: %v", err)
|
||||||
}
|
}
|
||||||
agent, err := NewAgent(conf, os.Stderr)
|
agent, err := NewAgent(conf, os.Stderr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -104,30 +96,16 @@ func TestAgent_RPCPing(t *testing.T) {
|
||||||
|
|
||||||
func TestAgent_ServerConfig(t *testing.T) {
|
func TestAgent_ServerConfig(t *testing.T) {
|
||||||
conf := DefaultConfig()
|
conf := DefaultConfig()
|
||||||
|
conf.DevMode = true // allow localhost for advertise addrs
|
||||||
a := &Agent{config: conf}
|
a := &Agent{config: conf}
|
||||||
testlogger := getTestLogger(t)
|
|
||||||
dev := false
|
|
||||||
|
|
||||||
// Returns error on bad serf addr
|
|
||||||
conf.AdvertiseAddrs.Serf = "nope"
|
|
||||||
_, err := a.serverConfig()
|
|
||||||
if err == nil || !strings.Contains(err.Error(), "Failed to parse Serf") {
|
|
||||||
t.Fatalf("expected serf address error, got: %#v", err)
|
|
||||||
}
|
|
||||||
conf.AdvertiseAddrs.Serf = "127.0.0.1:4000"
|
conf.AdvertiseAddrs.Serf = "127.0.0.1:4000"
|
||||||
|
|
||||||
// Returns error on bad rpc addr
|
|
||||||
conf.AdvertiseAddrs.RPC = "nope"
|
|
||||||
_, err = a.serverConfig()
|
|
||||||
if err == nil || !strings.Contains(err.Error(), "Failed to parse RPC") {
|
|
||||||
t.Fatalf("expected rpc address error, got: %#v", err)
|
|
||||||
}
|
|
||||||
conf.AdvertiseAddrs.RPC = "127.0.0.1:4001"
|
conf.AdvertiseAddrs.RPC = "127.0.0.1:4001"
|
||||||
conf.AdvertiseAddrs.HTTP = "10.10.11.1:4005"
|
conf.AdvertiseAddrs.HTTP = "10.10.11.1:4005"
|
||||||
|
|
||||||
// Parses the advertise addrs correctly
|
// Parses the advertise addrs correctly
|
||||||
if ok := conf.normalize(testlogger, dev); !ok {
|
if err := conf.normalizeAddrs(); err != nil {
|
||||||
t.Fatalf("failed to normalize config")
|
t.Fatalf("error normalizing config: %v", err)
|
||||||
}
|
}
|
||||||
out, err := a.serverConfig()
|
out, err := a.serverConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -149,8 +127,8 @@ func TestAgent_ServerConfig(t *testing.T) {
|
||||||
if addr := conf.AdvertiseAddrs.HTTP; addr != "10.10.11.1:4005" {
|
if addr := conf.AdvertiseAddrs.HTTP; addr != "10.10.11.1:4005" {
|
||||||
t.Fatalf("expect 10.11.11.1:4005, got: %v", addr)
|
t.Fatalf("expect 10.11.11.1:4005, got: %v", addr)
|
||||||
}
|
}
|
||||||
if addr := conf.Addresses.RPC; addr != "0.0.0.0:4647" {
|
if addr := conf.Addresses.RPC; addr != "0.0.0.0" {
|
||||||
t.Fatalf("expect 0.0.0.0:4001, got: %v", addr)
|
t.Fatalf("expect 0.0.0.0, got: %v", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets up the ports properly
|
// Sets up the ports properly
|
||||||
|
@ -159,8 +137,8 @@ func TestAgent_ServerConfig(t *testing.T) {
|
||||||
conf.Ports.RPC = 4003
|
conf.Ports.RPC = 4003
|
||||||
conf.Ports.Serf = 4004
|
conf.Ports.Serf = 4004
|
||||||
|
|
||||||
if ok := conf.normalize(testlogger, dev); !ok {
|
if err := conf.normalizeAddrs(); err != nil {
|
||||||
t.Fatalf("failed to normalize config")
|
t.Fatalf("error normalizing config: %v", err)
|
||||||
}
|
}
|
||||||
out, err = a.serverConfig()
|
out, err = a.serverConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -182,8 +160,8 @@ func TestAgent_ServerConfig(t *testing.T) {
|
||||||
conf.AdvertiseAddrs.RPC = ""
|
conf.AdvertiseAddrs.RPC = ""
|
||||||
conf.AdvertiseAddrs.Serf = "10.0.0.12:4004"
|
conf.AdvertiseAddrs.Serf = "10.0.0.12:4004"
|
||||||
|
|
||||||
if ok := conf.normalize(testlogger, dev); !ok {
|
if err := conf.normalizeAddrs(); err != nil {
|
||||||
t.Fatalf("failed to normalize config")
|
t.Fatalf("error normalizing config: %v", err)
|
||||||
}
|
}
|
||||||
out, err = a.serverConfig()
|
out, err = a.serverConfig()
|
||||||
fmt.Println(conf.Addresses.RPC)
|
fmt.Println(conf.Addresses.RPC)
|
||||||
|
@ -202,28 +180,37 @@ func TestAgent_ServerConfig(t *testing.T) {
|
||||||
if port := out.SerfConfig.MemberlistConfig.BindPort; port != 4004 {
|
if port := out.SerfConfig.MemberlistConfig.BindPort; port != 4004 {
|
||||||
t.Fatalf("expect 4648, got: ^d", port)
|
t.Fatalf("expect 4648, got: ^d", port)
|
||||||
}
|
}
|
||||||
if addr := conf.Addresses.HTTP; addr != "127.0.0.2:4646" {
|
if addr := conf.Addresses.HTTP; addr != "127.0.0.2" {
|
||||||
|
t.Fatalf("expect 127.0.0.2, got: %s", addr)
|
||||||
|
}
|
||||||
|
if addr := conf.Addresses.RPC; addr != "127.0.0.2" {
|
||||||
|
t.Fatalf("expect 127.0.0.2, got: %s", addr)
|
||||||
|
}
|
||||||
|
if addr := conf.Addresses.Serf; addr != "127.0.0.2" {
|
||||||
|
t.Fatalf("expect 10.0.0.12, got: %s", addr)
|
||||||
|
}
|
||||||
|
if addr := conf.normalizedAddrs.HTTP; addr != "127.0.0.2:4646" {
|
||||||
t.Fatalf("expect 127.0.0.2:4646, got: %s", addr)
|
t.Fatalf("expect 127.0.0.2:4646, got: %s", addr)
|
||||||
}
|
}
|
||||||
if addr := conf.Addresses.RPC; addr != "127.0.0.2:4003" {
|
if addr := conf.normalizedAddrs.RPC; addr != "127.0.0.2:4003" {
|
||||||
t.Fatalf("expect 127.0.0.2:4003, got: %s", addr)
|
t.Fatalf("expect 127.0.0.2:4003, got: %s", addr)
|
||||||
}
|
}
|
||||||
if addr := conf.Addresses.Serf; addr != "127.0.0.2:4004" {
|
if addr := conf.normalizedAddrs.Serf; addr != "127.0.0.2:4004" {
|
||||||
t.Fatalf("expect 10.0.0.12:4004, got: %s", addr)
|
t.Fatalf("expect 10.0.0.12:4004, got: %s", addr)
|
||||||
}
|
}
|
||||||
if addr := conf.AdvertiseAddrs.HTTP; addr != "10.0.0.10:4646" {
|
if addr := conf.AdvertiseAddrs.HTTP; addr != "10.0.0.10:4646" {
|
||||||
t.Fatalf("expect 10.0.0.10:4646, got: %s", addr)
|
t.Fatalf("expect 10.0.0.10:4646, got: %s", addr)
|
||||||
}
|
}
|
||||||
if addr := conf.AdvertiseAddrs.RPC; addr != "127.0.0.3:4003" {
|
if addr := conf.AdvertiseAddrs.RPC; addr != "127.0.0.2:4003" {
|
||||||
t.Fatalf("expect 127.0.0.3:4003, got: %s", addr)
|
t.Fatalf("expect 127.0.0.2:4003, got: %s", addr)
|
||||||
}
|
}
|
||||||
if addr := conf.AdvertiseAddrs.Serf; addr != "10.0.0.12:4004" {
|
if addr := conf.AdvertiseAddrs.Serf; addr != "10.0.0.12:4004" {
|
||||||
t.Fatalf("expect 10.0.0.12:4004, got: %s", addr)
|
t.Fatalf("expect 10.0.0.12:4004, got: %s", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.Server.NodeGCThreshold = "42g"
|
conf.Server.NodeGCThreshold = "42g"
|
||||||
if ok := conf.normalize(testlogger, dev); !ok {
|
if err := conf.normalizeAddrs(); err != nil {
|
||||||
t.Fatalf("failed to normalize config")
|
t.Fatalf("error normalizing config: %v", err)
|
||||||
}
|
}
|
||||||
out, err = a.serverConfig()
|
out, err = a.serverConfig()
|
||||||
if err == nil || !strings.Contains(err.Error(), "unknown unit") {
|
if err == nil || !strings.Contains(err.Error(), "unknown unit") {
|
||||||
|
@ -231,8 +218,8 @@ func TestAgent_ServerConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.Server.NodeGCThreshold = "10s"
|
conf.Server.NodeGCThreshold = "10s"
|
||||||
if ok := conf.normalize(testlogger, dev); !ok {
|
if err := conf.normalizeAddrs(); err != nil {
|
||||||
t.Fatalf("failed to normalize config")
|
t.Fatalf("error normalizing config: %v", err)
|
||||||
}
|
}
|
||||||
out, err = a.serverConfig()
|
out, err = a.serverConfig()
|
||||||
if threshold := out.NodeGCThreshold; threshold != time.Second*10 {
|
if threshold := out.NodeGCThreshold; threshold != time.Second*10 {
|
||||||
|
@ -240,8 +227,8 @@ func TestAgent_ServerConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.Server.HeartbeatGrace = "42g"
|
conf.Server.HeartbeatGrace = "42g"
|
||||||
if ok := conf.normalize(testlogger, dev); !ok {
|
if err := conf.normalizeAddrs(); err != nil {
|
||||||
t.Fatalf("failed to normalize config")
|
t.Fatalf("error normalizing config: %v", err)
|
||||||
}
|
}
|
||||||
out, err = a.serverConfig()
|
out, err = a.serverConfig()
|
||||||
if err == nil || !strings.Contains(err.Error(), "unknown unit") {
|
if err == nil || !strings.Contains(err.Error(), "unknown unit") {
|
||||||
|
@ -249,8 +236,8 @@ func TestAgent_ServerConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.Server.HeartbeatGrace = "37s"
|
conf.Server.HeartbeatGrace = "37s"
|
||||||
if ok := conf.normalize(testlogger, dev); !ok {
|
if err := conf.normalizeAddrs(); err != nil {
|
||||||
t.Fatalf("failed to normalize config")
|
t.Fatalf("error normalizing config: %v", err)
|
||||||
}
|
}
|
||||||
out, err = a.serverConfig()
|
out, err = a.serverConfig()
|
||||||
if threshold := out.HeartbeatGrace; threshold != time.Second*37 {
|
if threshold := out.HeartbeatGrace; threshold != time.Second*37 {
|
||||||
|
@ -267,8 +254,8 @@ func TestAgent_ServerConfig(t *testing.T) {
|
||||||
conf.Ports.HTTP = 4646
|
conf.Ports.HTTP = 4646
|
||||||
conf.Ports.RPC = 4647
|
conf.Ports.RPC = 4647
|
||||||
conf.Ports.Serf = 4648
|
conf.Ports.Serf = 4648
|
||||||
if ok := conf.normalize(testlogger, dev); !ok {
|
if err := conf.normalizeAddrs(); err != nil {
|
||||||
t.Fatalf("failed to normalize config")
|
t.Fatalf("error normalizing config: %v", err)
|
||||||
}
|
}
|
||||||
out, err = a.serverConfig()
|
out, err = a.serverConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -280,13 +267,22 @@ func TestAgent_ServerConfig(t *testing.T) {
|
||||||
if addr := out.SerfConfig.MemberlistConfig.BindAddr; addr != "127.0.0.3" {
|
if addr := out.SerfConfig.MemberlistConfig.BindAddr; addr != "127.0.0.3" {
|
||||||
t.Fatalf("expect 127.0.0.3, got: %s", addr)
|
t.Fatalf("expect 127.0.0.3, got: %s", addr)
|
||||||
}
|
}
|
||||||
if addr := conf.Addresses.HTTP; addr != "127.0.0.3:4646" {
|
if addr := conf.Addresses.HTTP; addr != "127.0.0.3" {
|
||||||
|
t.Fatalf("expect 127.0.0.3, got: %s", addr)
|
||||||
|
}
|
||||||
|
if addr := conf.Addresses.RPC; addr != "127.0.0.3" {
|
||||||
|
t.Fatalf("expect 127.0.0.3, got: %s", addr)
|
||||||
|
}
|
||||||
|
if addr := conf.Addresses.Serf; addr != "127.0.0.3" {
|
||||||
|
t.Fatalf("expect 127.0.0.3, got: %s", addr)
|
||||||
|
}
|
||||||
|
if addr := conf.normalizedAddrs.HTTP; addr != "127.0.0.3:4646" {
|
||||||
t.Fatalf("expect 127.0.0.3:4646, got: %s", addr)
|
t.Fatalf("expect 127.0.0.3:4646, got: %s", addr)
|
||||||
}
|
}
|
||||||
if addr := conf.Addresses.RPC; addr != "127.0.0.3:4647" {
|
if addr := conf.normalizedAddrs.RPC; addr != "127.0.0.3:4647" {
|
||||||
t.Fatalf("expect 127.0.0.3:4647, got: %s", addr)
|
t.Fatalf("expect 127.0.0.3:4647, got: %s", addr)
|
||||||
}
|
}
|
||||||
if addr := conf.Addresses.Serf; addr != "127.0.0.3:4648" {
|
if addr := conf.normalizedAddrs.Serf; addr != "127.0.0.3:4648" {
|
||||||
t.Fatalf("expect 127.0.0.3:4648, got: %s", addr)
|
t.Fatalf("expect 127.0.0.3:4648, got: %s", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,8 +321,8 @@ func TestAgent_ClientConfig(t *testing.T) {
|
||||||
conf.Addresses.HTTP = "127.0.0.1"
|
conf.Addresses.HTTP = "127.0.0.1"
|
||||||
conf.Ports.HTTP = 5678
|
conf.Ports.HTTP = 5678
|
||||||
|
|
||||||
if ok := conf.normalize(getTestLogger(t), conf.DevMode); !ok {
|
if err := conf.normalizeAddrs(); err != nil {
|
||||||
t.Fatalf("error normalizing config")
|
t.Fatalf("error normalizing config: %v", err)
|
||||||
}
|
}
|
||||||
c, err := a.clientConfig()
|
c, err := a.clientConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -344,8 +340,8 @@ func TestAgent_ClientConfig(t *testing.T) {
|
||||||
conf.Client.Enabled = true
|
conf.Client.Enabled = true
|
||||||
conf.Addresses.HTTP = "127.0.0.1"
|
conf.Addresses.HTTP = "127.0.0.1"
|
||||||
|
|
||||||
if ok := conf.normalize(getTestLogger(t), conf.DevMode); !ok {
|
if err := conf.normalizeAddrs(); err != nil {
|
||||||
t.Fatalf("error normalizing config")
|
t.Fatalf("error normalizing config: %v", err)
|
||||||
}
|
}
|
||||||
c, err = a.clientConfig()
|
c, err = a.clientConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -196,7 +196,14 @@ func (c *Command) readConfig() *Config {
|
||||||
// Merge any CLI options over config file options
|
// Merge any CLI options over config file options
|
||||||
config = config.Merge(cmdConfig)
|
config = config.Merge(cmdConfig)
|
||||||
|
|
||||||
if ok := config.normalize(c.Ui.Error, dev); !ok {
|
// Set the version info
|
||||||
|
config.Revision = c.Revision
|
||||||
|
config.Version = c.Version
|
||||||
|
config.VersionPrerelease = c.VersionPrerelease
|
||||||
|
|
||||||
|
// Normalize binds, ports, addresses, and advertise
|
||||||
|
if err := config.normalizeAddrs(); err != nil {
|
||||||
|
c.Ui.Error(err.Error())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +212,17 @@ func (c *Command) readConfig() *Config {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.Server.EncryptKey != "" {
|
||||||
|
if _, err := config.Server.EncryptBytes(); err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Invalid encryption key: %s", err))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
keyfile := filepath.Join(config.DataDir, serfKeyring)
|
||||||
|
if _, err := os.Stat(keyfile); err == nil {
|
||||||
|
c.Ui.Warn("WARNING: keyring exists but -encrypt given, using keyring")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the RetryInterval.
|
// Parse the RetryInterval.
|
||||||
dur, err := time.ParseDuration(config.Server.RetryInterval)
|
dur, err := time.ParseDuration(config.Server.RetryInterval)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -61,7 +61,7 @@ func TestCommand_Args(t *testing.T) {
|
||||||
|
|
||||||
// To prevent test failures on hosts whose hostname resolves to
|
// To prevent test failures on hosts whose hostname resolves to
|
||||||
// a loopback address, we must append a bind address
|
// a loopback address, we must append a bind address
|
||||||
tc.args = append(tc.args, "-bind=127.0.0.1")
|
tc.args = append(tc.args, "-bind=169.254.0.1")
|
||||||
if code := cmd.Run(tc.args); code != 1 {
|
if code := cmd.Run(tc.args); code != 1 {
|
||||||
t.Fatalf("args: %v\nexit: %d\n", tc.args, code)
|
t.Fatalf("args: %v\nexit: %d\n", tc.args, code)
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,8 +46,13 @@ type Config struct {
|
||||||
Ports *Ports `mapstructure:"ports"`
|
Ports *Ports `mapstructure:"ports"`
|
||||||
|
|
||||||
// Addresses is used to override the network addresses we bind to.
|
// Addresses is used to override the network addresses we bind to.
|
||||||
|
//
|
||||||
|
// Use normalizedAddrs if you need the host+port to bind to.
|
||||||
Addresses *Addresses `mapstructure:"addresses"`
|
Addresses *Addresses `mapstructure:"addresses"`
|
||||||
|
|
||||||
|
// normalizedAddr is set to the Address+Port by normalizeAddrs()
|
||||||
|
normalizedAddrs *Addresses
|
||||||
|
|
||||||
// AdvertiseAddrs is used to control the addresses we advertise.
|
// AdvertiseAddrs is used to control the addresses we advertise.
|
||||||
AdvertiseAddrs *AdvertiseAddrs `mapstructure:"advertise"`
|
AdvertiseAddrs *AdvertiseAddrs `mapstructure:"advertise"`
|
||||||
|
|
||||||
|
@ -335,8 +340,8 @@ type Telemetry struct {
|
||||||
CirconusBrokerSelectTag string `mapstructure:"circonus_broker_select_tag"`
|
CirconusBrokerSelectTag string `mapstructure:"circonus_broker_select_tag"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ports is used to encapsulate the various ports we bind to for network
|
// Ports encapsulates the various ports we bind to for network services. If any
|
||||||
// services. If any are not specified then the defaults are used instead.
|
// are not specified then the defaults are used instead.
|
||||||
type Ports struct {
|
type Ports struct {
|
||||||
HTTP int `mapstructure:"http"`
|
HTTP int `mapstructure:"http"`
|
||||||
RPC int `mapstructure:"rpc"`
|
RPC int `mapstructure:"rpc"`
|
||||||
|
@ -352,8 +357,8 @@ type Addresses struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdvertiseAddrs is used to control the addresses we advertise out for
|
// AdvertiseAddrs is used to control the addresses we advertise out for
|
||||||
// different network services. Not all network services support an
|
// different network services. All are optional and default to BindAddr and
|
||||||
// advertise address. All are optional and default to BindAddr.
|
// their default Port.
|
||||||
type AdvertiseAddrs struct {
|
type AdvertiseAddrs struct {
|
||||||
HTTP string `mapstructure:"http"`
|
HTTP string `mapstructure:"http"`
|
||||||
RPC string `mapstructure:"rpc"`
|
RPC string `mapstructure:"rpc"`
|
||||||
|
@ -658,137 +663,116 @@ func (c *Config) Merge(b *Config) *Config {
|
||||||
return &result
|
return &result
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalize config to set defaults and prevent nil derefence panics.
|
// normalize Addresses and AdvertiseAddrs to always be initialized and have
|
||||||
|
// sane defaults.
|
||||||
|
func (c *Config) normalizeAddrs() error {
|
||||||
|
c.Addresses.HTTP = normalizeBind(c.Addresses.HTTP, c.BindAddr)
|
||||||
|
c.Addresses.RPC = normalizeBind(c.Addresses.RPC, c.BindAddr)
|
||||||
|
c.Addresses.Serf = normalizeBind(c.Addresses.Serf, c.BindAddr)
|
||||||
|
c.normalizedAddrs = &Addresses{
|
||||||
|
HTTP: fmt.Sprintf("%s:%d", c.Addresses.HTTP, c.Ports.HTTP),
|
||||||
|
RPC: fmt.Sprintf("%s:%d", c.Addresses.RPC, c.Ports.RPC),
|
||||||
|
Serf: fmt.Sprintf("%s:%d", c.Addresses.Serf, c.Ports.Serf),
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, err := normalizeAdvertise(c.AdvertiseAddrs.HTTP, c.Addresses.HTTP, c.Ports.HTTP, c.DevMode)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to parse HTTP advertise address: %v", err)
|
||||||
|
}
|
||||||
|
c.AdvertiseAddrs.HTTP = addr
|
||||||
|
|
||||||
|
addr, err = normalizeAdvertise(c.AdvertiseAddrs.RPC, c.Addresses.RPC, c.Ports.RPC, c.DevMode)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to parse RPC advertise address: %v", err)
|
||||||
|
}
|
||||||
|
c.AdvertiseAddrs.RPC = addr
|
||||||
|
|
||||||
|
addr, err = normalizeAdvertise(c.AdvertiseAddrs.Serf, c.Addresses.Serf, c.Ports.Serf, c.DevMode)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to parse Serf advertise address: %v", err)
|
||||||
|
}
|
||||||
|
c.AdvertiseAddrs.Serf = addr
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalizeBind returns a normalized bind address.
|
||||||
//
|
//
|
||||||
// Returns true if config is ok and false on errors. Since some normalization
|
// If addr is set it is used, if not the default bind address is used.
|
||||||
// issues aren't fatal a logger must be provided to emit warnings.
|
func normalizeBind(addr, bind string) string {
|
||||||
func (c *Config) normalize(logger func(string), dev bool) bool {
|
if addr == "" {
|
||||||
// Set the version info
|
return bind
|
||||||
c.Revision = c.Revision
|
|
||||||
c.Version = c.Version
|
|
||||||
c.VersionPrerelease = c.VersionPrerelease
|
|
||||||
|
|
||||||
// Normalize addresses
|
|
||||||
bind := c.BindAddr
|
|
||||||
if err := normalizeBind(&c.Addresses.HTTP, bind, &c.Ports.HTTP); err != nil {
|
|
||||||
logger(err.Error())
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
if err := normalizeBind(&c.Addresses.RPC, bind, &c.Ports.RPC); err != nil {
|
return addr
|
||||||
logger(err.Error())
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if err := normalizeBind(&c.Addresses.Serf, bind, &c.Ports.Serf); err != nil {
|
|
||||||
logger(err.Error())
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := normalizeAdvertise(&c.AdvertiseAddrs.HTTP, bind, c.Ports.HTTP, dev); err != nil {
|
// normalizeAdvertise returns a normalized advertise address.
|
||||||
logger(err.Error())
|
//
|
||||||
return false
|
// If addr is set, it is used and the default port is appended if no port is
|
||||||
}
|
// set.
|
||||||
if err := normalizeAdvertise(&c.AdvertiseAddrs.RPC, bind, c.Ports.RPC, dev); err != nil {
|
//
|
||||||
logger(err.Error())
|
// If addr is not set and bind is a valid address, the returned string is the
|
||||||
return false
|
// bind+port.
|
||||||
}
|
//
|
||||||
if err := normalizeAdvertise(&c.AdvertiseAddrs.Serf, bind, c.Ports.Serf, dev); err != nil {
|
// If addr is not set and bind is not a valid advertise address, the hostname
|
||||||
logger(err.Error())
|
// is resolved and returned with the port.
|
||||||
return false
|
//
|
||||||
}
|
// Loopback is only considered a valid advertise address in dev mode.
|
||||||
|
func normalizeAdvertise(addr string, bind string, defport int, dev bool) (string, error) {
|
||||||
if c.Server.EncryptKey != "" {
|
if addr != "" {
|
||||||
if _, err := c.Server.EncryptBytes(); err != nil {
|
|
||||||
logger(fmt.Sprintf("Invalid encryption key: %s", err))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
keyfile := filepath.Join(c.DataDir, serfKeyring)
|
|
||||||
if _, err := os.Stat(keyfile); err == nil {
|
|
||||||
logger("WARNING: keyring exists but -encrypt given, using keyring")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use normalizeAdvertise(&config.AdvertiseAddrs.<Service>, <Port>) to
|
|
||||||
// retrieve a default address for advertising if one isn't set.
|
|
||||||
func normalizeAdvertise(addr *string, bind string, defport int, dev bool) error {
|
|
||||||
if *addr != "" {
|
|
||||||
// Default to using manually configured address
|
// Default to using manually configured address
|
||||||
_, _, err := net.SplitHostPort(*addr)
|
_, _, err := net.SplitHostPort(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !isMissingPort(err) {
|
if !isMissingPort(err) {
|
||||||
return fmt.Errorf("Error parsing advertise address %q: %v", *addr, err)
|
return "", fmt.Errorf("Error parsing advertise address %q: %v", addr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// missing port, append the default
|
// missing port, append the default
|
||||||
newaddr := fmt.Sprintf("%s:%d", *addr, defport)
|
return fmt.Sprintf("%s:%d", addr, defport), nil
|
||||||
*addr = newaddr
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return nil
|
return addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to Bind address if it's not 0.0.0.0
|
// Fallback to bind address first, and then try resolving the local hostname
|
||||||
if bind != "0.0.0.0" {
|
ips, err := net.LookupIP(bind)
|
||||||
newaddr := fmt.Sprintf("%s:%d", bind, defport)
|
if err != nil {
|
||||||
*addr = newaddr
|
return "", fmt.Errorf("Error resolving bind address %q: %v", bind, err)
|
||||||
return nil
|
}
|
||||||
|
|
||||||
|
// Return the first unicast address
|
||||||
|
for _, ip := range ips {
|
||||||
|
if ip.IsLinkLocalUnicast() || ip.IsGlobalUnicast() {
|
||||||
|
return fmt.Sprintf("%s:%d", ip, defport), nil
|
||||||
|
}
|
||||||
|
if ip.IsLoopback() && dev {
|
||||||
|
// loopback is fine for dev mode
|
||||||
|
return fmt.Sprintf("%s:%d", ip, defport), nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// As a last resort resolve the hostname and use it if it's not
|
// As a last resort resolve the hostname and use it if it's not
|
||||||
// localhost (as localhost is never a sensible default)
|
// localhost (as localhost is never a sensible default)
|
||||||
host, err := os.Hostname()
|
host, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to get hostname to set advertise address: %v", err)
|
return "", fmt.Errorf("Unable to get hostname to set advertise address: %v", err)
|
||||||
}
|
}
|
||||||
ip, err := net.ResolveIPAddr("ip", host)
|
|
||||||
|
ips, err = net.LookupIP(host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//TODO It'd be nice if we could advertise unresolvable
|
return "", fmt.Errorf("Error resolving hostname %q for advertise address: %v", host, err)
|
||||||
// addresses for configurations where this process may have
|
|
||||||
// different name resolution than the rest of the cluster.
|
|
||||||
// Unfortunately both serf/memberlist and Nomad's raft layer
|
|
||||||
// require resovlable advertise addresses.
|
|
||||||
return fmt.Errorf("Unable to resolve hostname to set advertise address: %v", err)
|
|
||||||
}
|
|
||||||
if ip.IP.IsLoopback() && !dev {
|
|
||||||
return fmt.Errorf("Unable to select default advertise address as hostname resolves to localhost")
|
|
||||||
}
|
|
||||||
newaddr := fmt.Sprintf("%s:%d", ip.IP.String(), defport)
|
|
||||||
*addr = newaddr
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeBind(addr *string, bind string, defport *int) error {
|
// Return the first unicast address
|
||||||
if *addr == "" {
|
for _, ip := range ips {
|
||||||
newaddr := fmt.Sprintf("%s:%d", bind, *defport)
|
if ip.IsLinkLocalUnicast() || ip.IsGlobalUnicast() {
|
||||||
*addr = newaddr
|
return fmt.Sprintf("%s:%d", ip, defport), nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
if ip.IsLoopback() && dev {
|
||||||
_, portstr, err := net.SplitHostPort(*addr)
|
// loopback is fine for dev mode
|
||||||
if err != nil {
|
return fmt.Sprintf("%s:%d", ip, defport), nil
|
||||||
if !isMissingPort(err) {
|
|
||||||
return fmt.Errorf("Error parsing bind address %q: %v", err, *addr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// missing port, add default
|
|
||||||
newaddr := fmt.Sprintf("%s:%d", *addr, *defport)
|
|
||||||
*addr = newaddr
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
return "", fmt.Errorf("No valid advertise addresses, please set `advertise` manually")
|
||||||
port, err := strconv.Atoi(portstr)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error parsing bind address's port: %q: %v", portstr, *addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the default port for this service to the bound port to keep
|
|
||||||
// configuration consistent.
|
|
||||||
if port != *defport {
|
|
||||||
*defport = port
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isMissingPort returns true if an error is a "missing port" error from
|
// isMissingPort returns true if an error is a "missing port" error from
|
||||||
|
|
|
@ -49,7 +49,7 @@ type HTTPServer struct {
|
||||||
// NewHTTPServer starts new HTTP server over the agent
|
// NewHTTPServer starts new HTTP server over the agent
|
||||||
func NewHTTPServer(agent *Agent, config *Config, logOutput io.Writer) (*HTTPServer, error) {
|
func NewHTTPServer(agent *Agent, config *Config, logOutput io.Writer) (*HTTPServer, error) {
|
||||||
// Start the listener
|
// Start the listener
|
||||||
lnAddr, err := net.ResolveTCPAddr("tcp", config.Addresses.HTTP)
|
lnAddr, err := net.ResolveTCPAddr("tcp", config.normalizedAddrs.HTTP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue