github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/command/agent/consul/namespaces_client.go (about) 1 package consul 2 3 import ( 4 "sort" 5 "sync" 6 "time" 7 8 "github.com/hashicorp/consul/api" 9 ) 10 11 const ( 12 // namespaceEnabledCacheTTL is how long to cache the response from Consul 13 // /v1/agent/self API, which is used to determine whether namespaces are 14 // available. 15 namespaceEnabledCacheTTL = 1 * time.Minute 16 ) 17 18 // NamespacesClient is a wrapper for the Consul NamespacesAPI, that is used to 19 // deal with Consul OSS vs Consul Enterprise behavior in listing namespaces. 20 type NamespacesClient struct { 21 namespacesAPI NamespaceAPI 22 agentAPI AgentAPI 23 24 lock sync.Mutex 25 enabled bool // namespaces requires Ent + Namespaces feature 26 updated time.Time // memoize response for a while 27 } 28 29 // NewNamespacesClient returns a NamespacesClient backed by a NamespaceAPI. 30 func NewNamespacesClient(namespacesAPI NamespaceAPI, agentAPI AgentAPI) *NamespacesClient { 31 return &NamespacesClient{ 32 namespacesAPI: namespacesAPI, 33 agentAPI: agentAPI, 34 } 35 } 36 37 func stale(updated, now time.Time) bool { 38 return now.After(updated.Add(namespaceEnabledCacheTTL)) 39 } 40 41 func (ns *NamespacesClient) allowable(now time.Time) bool { 42 ns.lock.Lock() 43 defer ns.lock.Unlock() 44 45 if !stale(ns.updated, now) { 46 return ns.enabled 47 } 48 49 self, err := ns.agentAPI.Self() 50 if err != nil { 51 return ns.enabled 52 } 53 54 sku, ok := SKU(self) 55 if !ok { 56 return ns.enabled 57 } 58 59 if sku != "ent" { 60 ns.enabled = false 61 ns.updated = now 62 return ns.enabled 63 } 64 65 ns.enabled = Namespaces(self) 66 ns.updated = now 67 return ns.enabled 68 } 69 70 // List returns a list of Consul Namespaces. 71 func (ns *NamespacesClient) List() ([]string, error) { 72 if !ns.allowable(time.Now()) { 73 // TODO(shoenig): lets return the empty string instead, that way we do not 74 // need to normalize at call sites later on 75 return []string{"default"}, nil 76 } 77 78 qo := &api.QueryOptions{ 79 AllowStale: true, 80 } 81 namespaces, _, err := ns.namespacesAPI.List(qo) 82 if err != nil { 83 return nil, err 84 } 85 86 result := make([]string, 0, len(namespaces)) 87 for _, namespace := range namespaces { 88 result = append(result, namespace.Name) 89 } 90 sort.Strings(result) 91 return result, nil 92 }