From 52a7ba4d4813be699e0a9172a0aec56f0591a223 Mon Sep 17 00:00:00 2001 From: "dan.markhasin" Date: Thu, 4 May 2023 09:44:32 +0300 Subject: [PATCH] deduplicate fallback dc list and remove the local DC --- consul.go | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/consul.go b/consul.go index 558d268..ec2bba9 100644 --- a/consul.go +++ b/consul.go @@ -3,6 +3,7 @@ package consulresolver import ( "context" "fmt" + "github.com/mitchellh/mapstructure" "log" "math" "reflect" @@ -17,6 +18,14 @@ import ( "go.uber.org/ratelimit" ) +type agentConfig struct { + DC string `mapstructure:"Datacenter"` +} + +type agentSelf struct { + Config agentConfig `mapstructure:"Config"` +} + // Balancer interface provides methods for selecting a target and updating its state type Balancer interface { // Select returns a *api.ServiceEntry describing the selected target. @@ -73,7 +82,23 @@ func NewConsulResolver(ctx context.Context, conf ResolverConfig) (*ServiceResolv conf.Log = log.Printf } - datacenters := append([]string{""}, conf.FallbackDatacenters...) + datacenters := []string{""} + if len(conf.FallbackDatacenters) > 0 { + seen := map[string]struct{}{} + // Exclude the local datacenter from the list of fallback datacenters + localDC, err := getLocalDatacenter(conf.Client.Agent()) + if err != nil { + return nil, errors.Wrap(err, "failed determining local consul datacenter") + } + + for _, dc := range conf.FallbackDatacenters { + if _, ok := seen[dc]; ok || dc == localDC { + continue + } + seen[dc] = struct{}{} + datacenters = append(datacenters, dc) + } + } resolver := &ServiceResolver{ log: conf.Log, @@ -223,3 +248,17 @@ func (r *ServiceResolver) getTargetsForUpdate(se []*api.ServiceEntry, priority i return se, false } + +func getLocalDatacenter(c *api.Agent) (string, error) { + res, err := c.Self() + if err != nil { + return "", errors.Wrap(err, "failed querying agent") + } + + var self agentSelf + if err := mapstructure.Decode(res, &self); err != nil { + return "", errors.Wrap(err, "failed decoding agent configuration") + } + + return self.Config.DC, nil +}