diff --git a/command/agent/config.go b/command/agent/config.go index ae53ba05d9..3e14134921 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -74,6 +74,11 @@ type DNSConfig struct { // stale read is performed. MaxStale time.Duration `mapstructure:"-"` MaxStaleRaw string `mapstructure:"max_stale" json:"-"` + + // OnlyPassing is used to determine whether to filter nodes + // whose health checks are in any non-passing state. By + // default, only nodes in a critical state are excluded. + OnlyPassing bool `mapstructure:"only_passing"` } // Config is the configuration that can be set for an Agent. @@ -835,6 +840,9 @@ func MergeConfig(a, b *Config) *Config { if b.DNSConfig.MaxStale != 0 { result.DNSConfig.MaxStale = b.DNSConfig.MaxStale } + if b.DNSConfig.OnlyPassing { + result.DNSConfig.OnlyPassing = true + } if b.CheckUpdateIntervalRaw != "" || b.CheckUpdateInterval != 0 { result.CheckUpdateInterval = b.CheckUpdateInterval } diff --git a/command/agent/config_test.go b/command/agent/config_test.go index 051d018697..292e1b2721 100644 --- a/command/agent/config_test.go +++ b/command/agent/config_test.go @@ -472,6 +472,17 @@ func TestDecodeConfig(t *testing.T) { t.Fatalf("bad: %#v", config) } + // DNS only passing + input = `{"dns_config": {"only_passing": true}}` + config, err = DecodeConfig(bytes.NewReader([]byte(input))) + if err != nil { + t.Fatalf("err: %s", err) + } + + if !config.DNSConfig.OnlyPassing { + t.Fatalf("bad: %#v", config) + } + // CheckUpdateInterval input = `{"check_update_interval": "10m"}` config, err = DecodeConfig(bytes.NewReader([]byte(input))) diff --git a/command/agent/dns.go b/command/agent/dns.go index 1b270bae7d..d4b2506414 100644 --- a/command/agent/dns.go +++ b/command/agent/dns.go @@ -554,7 +554,8 @@ OUTER: for i := 0; i < n; i++ { node := nodes[i] for _, check := range node.Checks { - if check.Status == structs.HealthCritical { + if check.Status == structs.HealthCritical || + (d.config.OnlyPassing && check.Status != structs.HealthPassing) { d.logger.Printf("[WARN] dns: node '%s' failing health check '%s: %s', dropping from service '%s'", node.Node.Node, check.CheckID, check.Name, node.Service.Service) nodes[i], nodes[n-1] = nodes[n-1], structs.CheckServiceNode{} diff --git a/website/source/docs/agent/options.html.markdown b/website/source/docs/agent/options.html.markdown index b9d7bef287..5144342a00 100644 --- a/website/source/docs/agent/options.html.markdown +++ b/website/source/docs/agent/options.html.markdown @@ -312,6 +312,10 @@ definitions support being updated during a reload. will set the truncated flag, indicating to clients that they should re-query using TCP to get the full set of records. + * `only_passing` - If set to true, any nodes whose healthchecks are not passing will be + excluded from DNS results. By default (or if set to false), only nodes whose healthchecks + are failing as critical will be excluded. + * `domain` - By default, Consul responds to DNS queries in the "consul." domain. This flag can be used to change that domain. All queries in this domain are assumed to be handled by Consul, and will not be recursively resolved.