Skip to content

Commit

Permalink
Add partitions func for listing partitions in the local datacenter
Browse files Browse the repository at this point in the history
  • Loading branch information
nathancoleman committed May 21, 2024
1 parent e9e921d commit 82bd836
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 4 deletions.
104 changes: 104 additions & 0 deletions dependency/catalog_partitions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package dependency

import (
"context"
"log"
"net/url"
"sort"
"time"

"github.com/pkg/errors"
)

var (
// Ensure implements
_ Dependency = (*CatalogPartitionsQuery)(nil)

// CatalogPartitionsQuerySleepTime is the amount of time to sleep between
// queries, since the endpoint does not support blocking queries.
CatalogPartitionsQuerySleepTime = 15 * time.Second
)

// CatalogPartitionsQuery is the representation of a requested catalog partitions
// dependency from inside a template.
type CatalogPartitionsQuery struct {
stopCh chan struct{}
}

// NewCatalogPartitionsQuery parses a string of the format @dc.
func NewCatalogPartitionsQuery() (*CatalogPartitionsQuery, error) {
return &CatalogPartitionsQuery{
stopCh: make(chan struct{}, 1),
}, nil
}

func (c *CatalogPartitionsQuery) Fetch(clients *ClientSet, opts *QueryOptions) (interface{}, *ResponseMetadata, error) {
opts = opts.Merge(&QueryOptions{})

log.Printf("[TRACE] %s: GET %s", c, &url.URL{
Path: "/v1/partitions",
RawQuery: opts.String(),
})

// This is certainly not elegant, but the partitions endpoint does not support
// blocking queries, so we are going to "fake it until we make it". When we
// first query, the LastIndex will be "0", meaning we should immediately
// return data, but future calls will include a LastIndex. If we have a
// LastIndex in the query metadata, sleep for 15 seconds before asking Consul
// again.
//
// This is probably okay given the frequency in which partitions actually
// change, but is technically not edge-triggering.
if opts.WaitIndex != 0 {
log.Printf("[TRACE] %s: long polling for %s", c, CatalogDatacentersQuerySleepTime)

select {
case <-c.stopCh:
return nil, nil, ErrStopped
case <-time.After(CatalogPartitionsQuerySleepTime):
}
}

// TODO Consider using a proper context
partitions, qm, err := clients.Consul().Partitions().List(context.Background(), opts.ToConsulOpts())
if err != nil {
return nil, nil, errors.Wrapf(err, c.String())
}

// TODO Consider returning full partition objects instead of just name
partitionNames := []string{}
for _, partition := range partitions {
if partition != nil {
partitionNames = append(partitionNames, partition.Name)
}
}

log.Printf("[TRACE] %s: returned %d results", c, len(partitionNames))

sort.Strings(partitionNames)

rm := &ResponseMetadata{
LastIndex: qm.LastIndex,
LastContact: qm.LastContact,
}

return partitionNames, rm, nil
}

// CanShare returns if this dependency is shareable.
// TODO What is this?
func (c *CatalogPartitionsQuery) CanShare() bool {
return true
}

func (c *CatalogPartitionsQuery) String() string {
return "catalog.partitions"
}

func (c *CatalogPartitionsQuery) Stop() {
close(c.stopCh)
}

func (c *CatalogPartitionsQuery) Type() Type {
return TypeConsul
}
10 changes: 10 additions & 0 deletions docs/templating-language.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ provides the following functions:
* [`safeLs`](#safels)
* [`node`](#node)
* [`nodes`](#nodes)
* [`partitions`](#partitions)
* [`peerings`](#peerings)
* [`secret`](#secret)
+ [Format](#format)
Expand Down Expand Up @@ -506,6 +507,15 @@ To query a different data center and order by shortest trip time to ourselves:
To access map data such as `TaggedAddresses` or `Meta`, use
[Go's text/template][text-template] map indexing.

### `partitions`

Query [Consul][consul] for all partitions.

```golang
{{ range partitions }}
{{ . }}{{ end }}
```

### `peerings`

Query [Consul][consul] for all peerings.
Expand Down
27 changes: 25 additions & 2 deletions template/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ import (

"github.com/BurntSushi/toml"
spewLib "github.com/davecgh/go-spew/spew"
dep "github.com/hashicorp/consul-template/dependency"
"github.com/hashicorp/consul/api"
socktmpl "github.com/hashicorp/go-sockaddr/template"
"github.com/imdario/mergo"
"github.com/pkg/errors"
"golang.org/x/text/cases"
"golang.org/x/text/language"
yaml "gopkg.in/yaml.v2"
"gopkg.in/yaml.v2"

dep "github.com/hashicorp/consul-template/dependency"
)

// now is function that represents the current time in UTC. This is here
Expand Down Expand Up @@ -74,6 +75,28 @@ func datacentersFunc(b *Brain, used, missing *dep.Set) func(ignore ...bool) ([]s
}
}

// partitionsFunc returns or accumulates partition dependencies.
func partitionsFunc(b *Brain, used, missing *dep.Set) func() ([]string, error) {
return func() ([]string, error) {
result := []string{}

d, err := dep.NewCatalogPartitionsQuery()
if err != nil {
return result, err
}

used.Add(d)

if value, ok := b.Recall(d); ok {
return value.([]string), nil
}

missing.Add(d)

return result, nil
}
}

// envFunc returns a function which checks the value of an environment variable.
// Invokers can specify their own environment, which takes precedences over any
// real environment variables
Expand Down
6 changes: 4 additions & 2 deletions template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import (
"text/template"

"github.com/Masterminds/sprig/v3"
"github.com/hashicorp/consul-template/config"
dep "github.com/hashicorp/consul-template/dependency"
"github.com/pkg/errors"
"golang.org/x/exp/maps"

"github.com/hashicorp/consul-template/config"
dep "github.com/hashicorp/consul-template/dependency"
)

var (
Expand Down Expand Up @@ -337,6 +338,7 @@ func funcMap(i *funcMapInput) template.FuncMap {
"safeLs": safeLsFunc(i.brain, i.used, i.missing),
"node": nodeFunc(i.brain, i.used, i.missing),
"nodes": nodesFunc(i.brain, i.used, i.missing),
"partitions": partitionsFunc(i.brain, i.used, i.missing),
"peerings": peeringsFunc(i.brain, i.used, i.missing),
"secret": secretFunc(i.brain, i.used, i.missing),
"secrets": secretsFunc(i.brain, i.used, i.missing),
Expand Down

0 comments on commit 82bd836

Please sign in to comment.