open-consul/vendor/github.com/hashicorp/go-bexpr/registry.go
Matt Keeler ac78c23021
Implement data filtering of some endpoints (#5579)
Fixes: #4222 

# Data Filtering

This PR will implement filtering for the following endpoints:

## Supported HTTP Endpoints

- `/agent/checks`
- `/agent/services`
- `/catalog/nodes`
- `/catalog/service/:service`
- `/catalog/connect/:service`
- `/catalog/node/:node`
- `/health/node/:node`
- `/health/checks/:service`
- `/health/service/:service`
- `/health/connect/:service`
- `/health/state/:state`
- `/internal/ui/nodes`
- `/internal/ui/services`

More can be added going forward and any endpoint which is used to list some data is a good candidate.

## Usage

When using the HTTP API a `filter` query parameter can be used to pass a filter expression to Consul. Filter Expressions take the general form of:

```
<selector> == <value>
<selector> != <value>
<value> in <selector>
<value> not in <selector>
<selector> contains <value>
<selector> not contains <value>
<selector> is empty
<selector> is not empty
not <other expression>
<expression 1> and <expression 2>
<expression 1> or <expression 2>
```

Normal boolean logic and precedence is supported. All of the actual filtering and evaluation logic is coming from the [go-bexpr](https://github.com/hashicorp/go-bexpr) library

## Other changes

Adding the `Internal.ServiceDump` RPC endpoint. This will allow the UI to filter services better.
2019-04-16 12:00:15 -04:00

60 lines
1.2 KiB
Go

package bexpr
import (
"reflect"
"sync"
)
var DefaultRegistry Registry = NewSyncRegistry()
type Registry interface {
GetFieldConfigurations(reflect.Type) (FieldConfigurations, error)
}
type SyncRegistry struct {
configurations map[reflect.Type]FieldConfigurations
lock sync.RWMutex
}
func NewSyncRegistry() *SyncRegistry {
return &SyncRegistry{
configurations: make(map[reflect.Type]FieldConfigurations),
}
}
func (r *SyncRegistry) GetFieldConfigurations(rtype reflect.Type) (FieldConfigurations, error) {
if r != nil {
r.lock.RLock()
configurations, ok := r.configurations[rtype]
r.lock.RUnlock()
if ok {
return configurations, nil
}
}
fields, err := generateFieldConfigurations(rtype)
if err != nil {
return nil, err
}
if r != nil {
r.lock.Lock()
r.configurations[rtype] = fields
r.lock.Unlock()
}
return fields, nil
}
type nilRegistry struct{}
// The pass through registry can be used to prevent using the default registry and thus storing
// any field configurations
var NilRegistry = (*nilRegistry)(nil)
func (r *nilRegistry) GetFieldConfigurations(rtype reflect.Type) (FieldConfigurations, error) {
fields, err := generateFieldConfigurations(rtype)
return fields, err
}