diff --git a/agent/config/builder.go b/agent/config/builder.go index 644bd0583a..980c163155 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -686,10 +686,10 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) { RejoinAfterLeave: b.boolVal(c.RejoinAfterLeave), RetryJoinIntervalLAN: b.durationVal("retry_interval", c.RetryJoinIntervalLAN), RetryJoinIntervalWAN: b.durationVal("retry_interval_wan", c.RetryJoinIntervalWAN), - RetryJoinLAN: c.RetryJoinLAN, + RetryJoinLAN: b.expandAllOptionalAddrs("retry_join", c.RetryJoinLAN), RetryJoinMaxAttemptsLAN: b.intVal(c.RetryJoinMaxAttemptsLAN), RetryJoinMaxAttemptsWAN: b.intVal(c.RetryJoinMaxAttemptsWAN), - RetryJoinWAN: c.RetryJoinWAN, + RetryJoinWAN: b.expandAllOptionalAddrs("retry_join_wan", c.RetryJoinWAN), SegmentName: b.stringVal(c.SegmentName), Segments: segments, SerfAdvertiseAddrLAN: serfAdvertiseAddrLAN, @@ -704,8 +704,8 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) { Services: services, SessionTTLMin: b.durationVal("session_ttl_min", c.SessionTTLMin), SkipLeaveOnInt: skipLeaveOnInt, - StartJoinAddrsLAN: c.StartJoinAddrsLAN, - StartJoinAddrsWAN: c.StartJoinAddrsWAN, + StartJoinAddrsLAN: b.expandAllOptionalAddrs("start_join", c.StartJoinAddrsLAN), + StartJoinAddrsWAN: b.expandAllOptionalAddrs("start_join_wan", c.StartJoinAddrsWAN), SyslogFacility: b.stringVal(c.SyslogFacility), TLSCipherSuites: b.tlsCipherSuites("tls_cipher_suites", c.TLSCipherSuites), TLSMinVersion: b.stringVal(c.TLSMinVersion), @@ -1132,6 +1132,43 @@ func (b *Builder) expandAddrs(name string, s *string) []net.Addr { return addrs } +// expandOptionalAddrs expands the go-sockaddr template in s and returns the +// result as a list of strings. If s does not contain a go-sockaddr template, +// the result list will contain the input string as a single element with no +// error set. In contrast to expandAddrs, expandOptionalAddrs does not validate +// if the result contains valid addresses and returns a list of strings. +// However, if the expansion of the go-sockaddr template fails an error is set. +func (b *Builder) expandOptionalAddrs(name string, s *string) []string { + if s == nil || *s == "" { + return nil + } + + x, err := template.Parse(*s) + if err != nil { + b.err = multierror.Append(b.err, fmt.Errorf("%s: error parsing %q: %s", name, s, err)) + return nil + } + + if x != *s { + // A template has been expanded, split the results from go-sockaddr + return strings.Fields(x) + } else { + // No template has been expanded, pass through the input + return []string{*s} + } +} + +func (b *Builder) expandAllOptionalAddrs(name string, addrs []string) []string { + out := make([]string, 0, len(addrs)) + for _, a := range addrs { + expanded := b.expandOptionalAddrs(name, &a) + if expanded != nil { + out = append(out, expanded...) + } + } + return out +} + // expandIPs expands the go-sockaddr template in s and returns a list of // *net.IPAddr. If one of the expanded addresses is a unix socket // address an error is set and nil is returned. diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index 78e7d577b1..d7cc2e18cd 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -1121,6 +1121,46 @@ func TestConfigFlagsAndEdgecases(t *testing.T) { rt.DataDir = dataDir }, }, + { + desc: "start_join address template", + args: []string{`-data-dir=` + dataDir}, + json: []string{`{ "start_join": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`}, + hcl: []string{`start_join = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`}, + patch: func(rt *RuntimeConfig) { + rt.StartJoinAddrsLAN = []string{"1.2.3.4", "4.3.2.1"} + rt.DataDir = dataDir + }, + }, + { + desc: "start_join_wan address template", + args: []string{`-data-dir=` + dataDir}, + json: []string{`{ "start_join_wan": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`}, + hcl: []string{`start_join_wan = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`}, + patch: func(rt *RuntimeConfig) { + rt.StartJoinAddrsWAN = []string{"1.2.3.4", "4.3.2.1"} + rt.DataDir = dataDir + }, + }, + { + desc: "retry_join address template", + args: []string{`-data-dir=` + dataDir}, + json: []string{`{ "retry_join": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`}, + hcl: []string{`retry_join = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`}, + patch: func(rt *RuntimeConfig) { + rt.RetryJoinLAN = []string{"1.2.3.4", "4.3.2.1"} + rt.DataDir = dataDir + }, + }, + { + desc: "retry_join_wan address template", + args: []string{`-data-dir=` + dataDir}, + json: []string{`{ "retry_join_wan": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`}, + hcl: []string{`retry_join_wan = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`}, + patch: func(rt *RuntimeConfig) { + rt.RetryJoinWAN = []string{"1.2.3.4", "4.3.2.1"} + rt.DataDir = dataDir + }, + }, // ------------------------------------------------------------ // precedence rules diff --git a/website/source/docs/agent/options.html.md b/website/source/docs/agent/options.html.md index 9ee1f5e0b6..3d4842f7a4 100644 --- a/website/source/docs/agent/options.html.md +++ b/website/source/docs/agent/options.html.md @@ -43,13 +43,16 @@ configuration reload. The options below are all specified on the command-line. -* `-advertise` - The advertise - address is used to change the address that we - advertise to other nodes in the cluster. By default, the [`-bind`](#_bind) address is - advertised. However, in some cases, there may be a routable address that cannot - be bound. This flag enables gossiping a different address to support this. - If this address is not routable, the node will be in a constant flapping state - as other nodes will treat the non-routability as a failure. +* `-advertise` - The + advertise address is used to change the address that we advertise to other + nodes in the cluster. By default, the [`-bind`](#_bind) address is advertised. + However, in some cases, there may be a routable address that cannot be bound. + This flag enables gossiping a different address to support this. If this + address is not routable, the node will be in a constant flapping state as + other nodes will treat the non-routability as a failure. In Consul 1.0 and + later this can be set to a + [go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr/template) + template. * `-advertise-wan` - The advertise WAN address is used to change the address that we advertise to server nodes @@ -61,7 +64,10 @@ The options below are all specified on the command-line. nodes gossiping through the public network for the WAN while using private VLANs for gossiping to each other and their client agents, and it allows client agents to be reached at this address when being accessed from a remote datacenter if the remote datacenter is configured - with `translate_wan_addrs`. + with `translate_wan_addrs`. In Consul 1.0 and + later this can be set to a + [go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr/template) + template * `-bootstrap` - This flag is used to control if a server is in "bootstrap" mode. It is important that @@ -90,23 +96,38 @@ at startup. If you specify "[::]", Consul will IPv6 address. If there are multiple public IPv6 addresses available, Consul 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. - -* `-serf-wan-bind` - 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), and if this is not specified, the `-bind` option is used. This - is available in Consul 0.7.1 and later. - -* `-serf-lan-bind` - 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), and if this is not specified, the `-bind` option is used. This is available in Consul 0.7.1 and later. - -* `-client` - The address to which - Consul will bind client interfaces, including the HTTP and DNS servers. By default, - this is "127.0.0.1", allowing only loopback connections. In Consul 1.0 and later + have any firewalls, be sure to allow both protocols. In Consul 1.0 and later this can be set to a space-separated list of addresses to bind to, or a [go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr/template) template that can potentially resolve to multiple addresses. +* `-serf-wan-bind` - + 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), and if this is not specified, the `-bind` option is used. This + is available in Consul 0.7.1 and later. In Consul 1.0 and later this can be + set to a + [go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr/template) + template + +* `-serf-lan-bind` - + 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), and if this is not specified, the `-bind` option is used. This + is available in Consul 0.7.1 and later. In Consul 1.0 and later this can be + set to a + [go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr/template) + template + +* `-client` - The address to which + Consul will bind client interfaces, including the HTTP and DNS servers. By + default, this is "127.0.0.1", allowing only loopback connections. In Consul + 1.0 and later this can be set to a space-separated list of addresses to bind + to, or a + [go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr/template) + template that can potentially resolve to multiple addresses. + * `-config-file` - A configuration file to load. For more information on the format of this file, read the [Configuration Files](#configuration_files) section. @@ -214,17 +235,23 @@ will exit with an error at startup. Note that using `retry_join` could be more appropriate to help mitigate node startup race conditions when automating a Consul cluster - deployment.\ + deployment. + + In Consul 1.1.0 and later this can be set to a + [go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr/template) + template * `-retry-join` - Similar to [`-join`](#_join) but allows retrying a join if the first attempt fails. This is useful for cases where you know the address will - eventually be available. The list can contain IPv4, IPv6, or DNS addresses. If - Consul is running on the non-default Serf LAN port, this must be specified as - well. IPv6 must use the "bracketed" syntax. If multiple values are given, they - are tried and retried in the order listed until the first succeeds. Here are - some examples: + eventually be available. The list can contain IPv4, IPv6, or DNS addresses. In + Consul 1.1.0 and later this can be set to a + [go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr/template) + template. If Consul is running on the non-default Serf LAN port, this must be + specified as well. IPv6 must use the "bracketed" syntax. If multiple values + are given, they are tried and retried in the order listed until the first + succeeds. Here are some examples: ```sh # Using a DNS entry @@ -510,17 +537,25 @@ will exit with an error at startup. with return code 1. By default, this is set to 0 which is interpreted as infinite retries. -* `-join-wan` - Address of another - wan agent to join upon starting up. This can be - specified multiple times to specify multiple WAN agents to join. If Consul is - unable to join with any of the specified addresses, agent startup will - fail. By default, the agent won't [`-join-wan`](#_join_wan) any nodes when it starts up. +* `-join-wan` - Address of + another wan agent to join upon starting up. This can be specified multiple + times to specify multiple WAN agents to join. If Consul is unable to join with + any of the specified addresses, agent startup will fail. By default, the agent + won't [`-join-wan`](#_join_wan) any nodes when it starts up. + + In Consul 1.1.0 and later this can be set to a + [go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr/template) + template. * `-retry-join-wan` - Similar to [`retry-join`](#_retry_join) but allows retrying a wan join if the first attempt fails. This is useful for cases where we know the address will become available eventually. As of Consul 0.9.3 [Cloud Auto-Joining](#cloud-auto-joining) is supported as well. + In Consul 1.1.0 and later this can be set to a + [go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr/template) + template + * `-retry-interval-wan` - Time to wait between [`-join-wan`](#_join_wan) attempts. Defaults to 30s.