2017-07-28 21:48:15 +00:00
|
|
|
package nomad
|
|
|
|
|
|
|
|
import (
|
2018-09-15 23:23:13 +00:00
|
|
|
"fmt"
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
"sort"
|
2017-08-14 13:34:31 +00:00
|
|
|
"strings"
|
2017-12-20 20:17:28 +00:00
|
|
|
"time"
|
2017-08-14 03:51:47 +00:00
|
|
|
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
"github.com/armon/go-metrics"
|
|
|
|
"github.com/hashicorp/go-hclog"
|
|
|
|
"github.com/hashicorp/go-memdb"
|
2018-09-15 23:23:13 +00:00
|
|
|
|
2017-10-13 21:36:02 +00:00
|
|
|
"github.com/hashicorp/nomad/acl"
|
2017-07-28 21:48:15 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/state"
|
2017-08-14 13:34:31 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
2017-07-28 21:48:15 +00:00
|
|
|
)
|
|
|
|
|
2017-08-04 22:18:49 +00:00
|
|
|
const (
|
2017-08-14 13:34:31 +00:00
|
|
|
// truncateLimit is the maximum number of matches that will be returned for a
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
// prefix for a specific context.
|
|
|
|
//
|
|
|
|
// Does not apply to fuzzy searching.
|
2017-08-04 22:18:49 +00:00
|
|
|
truncateLimit = 20
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2017-09-07 23:56:15 +00:00
|
|
|
// ossContexts are the oss contexts which are searched to find matches
|
|
|
|
// for a given prefix
|
2017-10-12 01:05:27 +00:00
|
|
|
ossContexts = []structs.Context{
|
|
|
|
structs.Allocs,
|
|
|
|
structs.Jobs,
|
|
|
|
structs.Nodes,
|
|
|
|
structs.Evals,
|
|
|
|
structs.Deployments,
|
2020-03-06 15:09:10 +00:00
|
|
|
structs.Plugins,
|
|
|
|
structs.Volumes,
|
2021-02-03 19:26:57 +00:00
|
|
|
structs.ScalingPolicies,
|
2022-06-20 03:39:00 +00:00
|
|
|
structs.SecureVariables,
|
2020-10-21 04:16:25 +00:00
|
|
|
structs.Namespaces,
|
2017-10-12 01:05:27 +00:00
|
|
|
}
|
2017-08-04 22:18:49 +00:00
|
|
|
)
|
2017-08-03 20:34:56 +00:00
|
|
|
|
2017-08-11 14:44:46 +00:00
|
|
|
// Search endpoint is used to look up matches for a given prefix and context
|
2017-08-10 19:24:11 +00:00
|
|
|
type Search struct {
|
2018-09-15 23:23:13 +00:00
|
|
|
srv *Server
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
logger hclog.Logger
|
2017-07-28 21:48:15 +00:00
|
|
|
}
|
|
|
|
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
// getPrefixMatches extracts matches for an iterator, and returns a list of ids for
|
2017-08-03 20:34:56 +00:00
|
|
|
// these matches.
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
func (s *Search) getPrefixMatches(iter memdb.ResultIterator, prefix string) ([]string, bool) {
|
2017-08-02 21:55:48 +00:00
|
|
|
var matches []string
|
|
|
|
|
2017-08-03 20:34:56 +00:00
|
|
|
for i := 0; i < truncateLimit; i++ {
|
2017-08-02 21:55:48 +00:00
|
|
|
raw := iter.Next()
|
|
|
|
if raw == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2017-08-04 15:08:12 +00:00
|
|
|
var id string
|
2017-08-07 14:16:24 +00:00
|
|
|
switch t := raw.(type) {
|
2017-08-14 13:34:31 +00:00
|
|
|
case *structs.Job:
|
2020-03-06 15:09:10 +00:00
|
|
|
id = t.ID
|
2017-08-14 13:34:31 +00:00
|
|
|
case *structs.Evaluation:
|
2020-03-06 15:09:10 +00:00
|
|
|
id = t.ID
|
2017-08-14 13:34:31 +00:00
|
|
|
case *structs.Allocation:
|
2020-03-06 15:09:10 +00:00
|
|
|
id = t.ID
|
2017-08-14 13:34:31 +00:00
|
|
|
case *structs.Node:
|
2020-03-06 15:09:10 +00:00
|
|
|
id = t.ID
|
2017-08-18 20:06:25 +00:00
|
|
|
case *structs.Deployment:
|
2020-03-06 15:09:10 +00:00
|
|
|
id = t.ID
|
|
|
|
case *structs.CSIPlugin:
|
|
|
|
id = t.ID
|
|
|
|
case *structs.CSIVolume:
|
|
|
|
id = t.ID
|
2021-02-03 19:26:57 +00:00
|
|
|
case *structs.ScalingPolicy:
|
|
|
|
id = t.ID
|
2020-10-21 04:16:25 +00:00
|
|
|
case *structs.Namespace:
|
|
|
|
id = t.Name
|
2022-06-20 03:39:00 +00:00
|
|
|
case *structs.SecureVariableEncrypted:
|
|
|
|
id = t.Path
|
2017-08-04 15:08:12 +00:00
|
|
|
default:
|
2017-09-07 23:56:15 +00:00
|
|
|
matchID, ok := getEnterpriseMatch(raw)
|
|
|
|
if !ok {
|
2018-09-15 23:23:13 +00:00
|
|
|
s.logger.Error("unexpected type for resources context", "type", fmt.Sprintf("%T", t))
|
2017-09-07 23:56:15 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
id = matchID
|
2017-08-02 21:55:48 +00:00
|
|
|
}
|
|
|
|
|
2017-08-14 13:34:31 +00:00
|
|
|
if !strings.HasPrefix(id, prefix) {
|
2017-08-11 13:33:12 +00:00
|
|
|
continue
|
2017-08-10 14:48:02 +00:00
|
|
|
}
|
|
|
|
|
2017-08-02 21:55:48 +00:00
|
|
|
matches = append(matches, id)
|
|
|
|
}
|
|
|
|
|
2017-08-07 17:23:32 +00:00
|
|
|
return matches, iter.Next() != nil
|
2017-08-02 21:55:48 +00:00
|
|
|
}
|
|
|
|
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
func (s *Search) getFuzzyMatches(iter memdb.ResultIterator, text string) (map[structs.Context][]structs.FuzzyMatch, map[structs.Context]bool) {
|
|
|
|
limitQuery := s.srv.config.SearchConfig.LimitQuery
|
|
|
|
limitResults := s.srv.config.SearchConfig.LimitResults
|
|
|
|
|
|
|
|
unsorted := make(map[structs.Context][]fuzzyMatch)
|
|
|
|
truncations := make(map[structs.Context]bool)
|
|
|
|
|
|
|
|
accumulateSet := func(limited bool, set map[structs.Context][]fuzzyMatch) {
|
|
|
|
for ctx, matches := range set {
|
|
|
|
for _, match := range matches {
|
|
|
|
if len(unsorted[ctx]) < limitResults {
|
|
|
|
unsorted[ctx] = append(unsorted[ctx], match)
|
|
|
|
} else {
|
|
|
|
// truncated by results limit
|
|
|
|
truncations[ctx] = true
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if limited {
|
|
|
|
// truncated by query limit
|
|
|
|
truncations[ctx] = true
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
accumulateSingle := func(limited bool, ctx structs.Context, match *fuzzyMatch) {
|
|
|
|
if match != nil {
|
|
|
|
if len(unsorted[ctx]) < limitResults {
|
|
|
|
unsorted[ctx] = append(unsorted[ctx], *match)
|
|
|
|
} else {
|
|
|
|
// truncated by results limit
|
|
|
|
truncations[ctx] = true
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if limited {
|
|
|
|
// truncated by query limit
|
|
|
|
truncations[ctx] = true
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
limited := func(i int, iter memdb.ResultIterator) bool {
|
|
|
|
if i == limitQuery-1 {
|
|
|
|
return iter.Next() != nil
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < limitQuery; i++ {
|
|
|
|
raw := iter.Next()
|
|
|
|
if raw == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
switch t := raw.(type) {
|
|
|
|
case *structs.Job:
|
|
|
|
set := s.fuzzyMatchesJob(t, text)
|
|
|
|
accumulateSet(limited(i, iter), set)
|
|
|
|
default:
|
|
|
|
ctx, match := s.fuzzyMatchSingle(raw, text)
|
|
|
|
accumulateSingle(limited(i, iter), ctx, match)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// sort the set of match results
|
|
|
|
for ctx := range unsorted {
|
|
|
|
sortSet(unsorted[ctx])
|
|
|
|
}
|
|
|
|
|
|
|
|
// create the result out of exported types
|
|
|
|
m := make(map[structs.Context][]structs.FuzzyMatch, len(unsorted))
|
|
|
|
for ctx, matches := range unsorted {
|
|
|
|
m[ctx] = make([]structs.FuzzyMatch, 0, len(matches))
|
|
|
|
for _, match := range matches {
|
|
|
|
m[ctx] = append(m[ctx], structs.FuzzyMatch{
|
|
|
|
ID: match.id,
|
|
|
|
Scope: match.scope,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return m, truncations
|
|
|
|
}
|
|
|
|
|
2021-04-16 22:56:03 +00:00
|
|
|
// fuzzyIndex returns the index of text in name, ignoring case.
|
|
|
|
// text is assumed to be lower case.
|
|
|
|
// -1 is returned if name does not contain text.
|
|
|
|
func fuzzyIndex(name, text string) int {
|
|
|
|
lower := strings.ToLower(name)
|
|
|
|
return strings.Index(lower, text)
|
|
|
|
}
|
|
|
|
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
// fuzzySingleMatch determines if the ID of raw is a fuzzy match with text.
|
|
|
|
// Returns the context and score or nil if there is no match.
|
|
|
|
func (s *Search) fuzzyMatchSingle(raw interface{}, text string) (structs.Context, *fuzzyMatch) {
|
|
|
|
var (
|
|
|
|
name string // fuzzy searchable name
|
|
|
|
scope []string
|
|
|
|
ctx structs.Context
|
|
|
|
)
|
|
|
|
|
|
|
|
switch t := raw.(type) {
|
|
|
|
case *structs.Node:
|
|
|
|
name = t.Name
|
|
|
|
scope = []string{t.ID}
|
|
|
|
ctx = structs.Nodes
|
|
|
|
case *structs.Namespace:
|
|
|
|
name = t.Name
|
|
|
|
ctx = structs.Namespaces
|
|
|
|
case *structs.Allocation:
|
|
|
|
name = t.Name
|
|
|
|
scope = []string{t.Namespace, t.ID}
|
|
|
|
ctx = structs.Allocs
|
|
|
|
case *structs.CSIPlugin:
|
|
|
|
name = t.ID
|
|
|
|
ctx = structs.Plugins
|
2022-06-20 03:39:00 +00:00
|
|
|
case *structs.SecureVariableEncrypted:
|
|
|
|
name = t.Path
|
|
|
|
scope = []string{t.Namespace, t.Path}
|
|
|
|
ctx = structs.SecureVariables
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
}
|
|
|
|
|
2021-04-16 22:56:03 +00:00
|
|
|
if idx := fuzzyIndex(name, text); idx >= 0 {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
return ctx, &fuzzyMatch{
|
|
|
|
id: name,
|
|
|
|
score: idx,
|
|
|
|
scope: scope,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// getFuzzyMatchesJob digs through j and extracts matches against several types
|
|
|
|
// of matchable Context. Results are categorized by Context and paired with their
|
|
|
|
// score, but are unsorted.
|
|
|
|
//
|
|
|
|
// job.name
|
|
|
|
// job|group.name
|
|
|
|
// job|group|service.name
|
|
|
|
// job|group|task.name
|
|
|
|
// job|group|task|service.name
|
|
|
|
// job|group|task|driver.{image,command,class}
|
|
|
|
func (*Search) fuzzyMatchesJob(j *structs.Job, text string) map[structs.Context][]fuzzyMatch {
|
|
|
|
sm := make(map[structs.Context][]fuzzyMatch)
|
|
|
|
ns := j.Namespace
|
|
|
|
job := j.ID
|
|
|
|
|
|
|
|
// job.name
|
2021-04-16 22:56:03 +00:00
|
|
|
if idx := fuzzyIndex(j.Name, text); idx >= 0 {
|
2021-04-16 23:03:36 +00:00
|
|
|
sm[structs.Jobs] = append(sm[structs.Jobs], score(j.Name, ns, idx, job))
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// job|group.name
|
|
|
|
for _, group := range j.TaskGroups {
|
2021-04-16 22:56:03 +00:00
|
|
|
if idx := fuzzyIndex(group.Name, text); idx >= 0 {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
sm[structs.Groups] = append(sm[structs.Groups], score(group.Name, ns, idx, job))
|
|
|
|
}
|
|
|
|
|
|
|
|
// job|group|service.name
|
|
|
|
for _, service := range group.Services {
|
2021-04-16 22:56:03 +00:00
|
|
|
if idx := fuzzyIndex(service.Name, text); idx >= 0 {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
sm[structs.Services] = append(sm[structs.Services], score(service.Name, ns, idx, job, group.Name))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// job|group|task.name
|
|
|
|
for _, task := range group.Tasks {
|
2021-04-16 22:56:03 +00:00
|
|
|
if idx := fuzzyIndex(task.Name, text); idx >= 0 {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
sm[structs.Tasks] = append(sm[structs.Tasks], score(task.Name, ns, idx, job, group.Name))
|
|
|
|
}
|
|
|
|
|
|
|
|
// job|group|task|service.name
|
|
|
|
for _, service := range task.Services {
|
2021-04-16 22:56:03 +00:00
|
|
|
if idx := fuzzyIndex(service.Name, text); idx >= 0 {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
sm[structs.Services] = append(sm[structs.Services], score(service.Name, ns, idx, job, group.Name, task.Name))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// job|group|task|config.{image,command,class}
|
|
|
|
switch task.Driver {
|
|
|
|
case "docker":
|
|
|
|
image := getConfigParam(task.Config, "image")
|
2021-04-16 22:56:03 +00:00
|
|
|
if idx := fuzzyIndex(image, text); idx >= 0 {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
sm[structs.Images] = append(sm[structs.Images], score(image, ns, idx, job, group.Name, task.Name))
|
|
|
|
}
|
|
|
|
case "exec", "raw_exec":
|
|
|
|
command := getConfigParam(task.Config, "command")
|
2021-04-16 22:56:03 +00:00
|
|
|
if idx := fuzzyIndex(command, text); idx >= 0 {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
sm[structs.Commands] = append(sm[structs.Commands], score(command, ns, idx, job, group.Name, task.Name))
|
|
|
|
}
|
|
|
|
case "java":
|
|
|
|
class := getConfigParam(task.Config, "class")
|
2021-04-16 22:56:03 +00:00
|
|
|
if idx := fuzzyIndex(class, text); idx >= 0 {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
sm[structs.Classes] = append(sm[structs.Classes], score(class, ns, idx, job, group.Name, task.Name))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return sm
|
|
|
|
}
|
|
|
|
|
|
|
|
func getConfigParam(config map[string]interface{}, param string) string {
|
|
|
|
if config == nil || config[param] == nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
s, ok := config[param].(string)
|
|
|
|
if !ok {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
type fuzzyMatch struct {
|
|
|
|
id string
|
|
|
|
scope []string
|
|
|
|
score int
|
|
|
|
}
|
|
|
|
|
|
|
|
func score(id, namespace string, score int, scope ...string) fuzzyMatch {
|
|
|
|
return fuzzyMatch{
|
|
|
|
id: id,
|
|
|
|
score: score,
|
|
|
|
scope: append([]string{namespace}, scope...),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func sortSet(matches []fuzzyMatch) {
|
|
|
|
sort.Slice(matches, func(a, b int) bool {
|
|
|
|
A, B := matches[a], matches[b]
|
|
|
|
|
|
|
|
// sort by index
|
|
|
|
switch {
|
|
|
|
case A.score < B.score:
|
|
|
|
return true
|
|
|
|
case B.score < A.score:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// shorter length matched text is more likely to be the thing being
|
|
|
|
// searched for (in theory)
|
|
|
|
//
|
|
|
|
// this also causes exact matches to score best, which is desirable
|
|
|
|
idA, idB := A.id, B.id
|
|
|
|
switch {
|
|
|
|
case len(idA) < len(idB):
|
|
|
|
return true
|
|
|
|
case len(idB) < len(idA):
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// same index and same length, break ties alphabetically
|
|
|
|
return idA < idB
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-08-03 20:34:56 +00:00
|
|
|
// getResourceIter takes a context and returns a memdb iterator specific to
|
|
|
|
// that context
|
2022-03-12 00:44:52 +00:00
|
|
|
func getResourceIter(context structs.Context, aclObj *acl.ACL, namespace, prefix string, ws memdb.WatchSet, store *state.StateStore) (memdb.ResultIterator, error) {
|
2017-08-03 15:59:27 +00:00
|
|
|
switch context {
|
2017-08-14 13:34:31 +00:00
|
|
|
case structs.Jobs:
|
2022-03-12 00:44:52 +00:00
|
|
|
return store.JobsByIDPrefix(ws, namespace, prefix)
|
2017-08-14 13:34:31 +00:00
|
|
|
case structs.Evals:
|
2022-03-12 00:44:52 +00:00
|
|
|
return store.EvalsByIDPrefix(ws, namespace, prefix, state.SortDefault)
|
2017-08-14 13:34:31 +00:00
|
|
|
case structs.Allocs:
|
2022-03-12 00:44:52 +00:00
|
|
|
return store.AllocsByIDPrefix(ws, namespace, prefix, state.SortDefault)
|
2017-08-14 13:34:31 +00:00
|
|
|
case structs.Nodes:
|
2022-03-12 00:44:52 +00:00
|
|
|
return store.NodesByIDPrefix(ws, prefix)
|
2017-08-18 20:06:25 +00:00
|
|
|
case structs.Deployments:
|
2022-03-12 00:44:52 +00:00
|
|
|
return store.DeploymentsByIDPrefix(ws, namespace, prefix, state.SortDefault)
|
2020-03-06 15:09:10 +00:00
|
|
|
case structs.Plugins:
|
2022-03-12 00:44:52 +00:00
|
|
|
return store.CSIPluginsByIDPrefix(ws, prefix)
|
2021-02-03 19:26:57 +00:00
|
|
|
case structs.ScalingPolicies:
|
2022-03-12 00:44:52 +00:00
|
|
|
return store.ScalingPoliciesByIDPrefix(ws, namespace, prefix)
|
2020-03-06 15:09:10 +00:00
|
|
|
case structs.Volumes:
|
2022-03-12 00:44:52 +00:00
|
|
|
return store.CSIVolumesByIDPrefix(ws, namespace, prefix)
|
2020-10-21 04:16:25 +00:00
|
|
|
case structs.Namespaces:
|
2022-03-12 00:44:52 +00:00
|
|
|
iter, err := store.NamespacesByNamePrefix(ws, prefix)
|
2020-10-21 04:16:25 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if aclObj == nil {
|
|
|
|
return iter, nil
|
|
|
|
}
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
return memdb.NewFilterIterator(iter, nsCapFilter(aclObj)), nil
|
2022-06-20 03:39:00 +00:00
|
|
|
case structs.SecureVariables:
|
|
|
|
iter, err := store.GetSecureVariablesByPrefix(ws, prefix)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if aclObj == nil {
|
|
|
|
return iter, nil
|
|
|
|
}
|
|
|
|
return memdb.NewFilterIterator(iter, nsCapFilter(aclObj)), nil
|
2017-08-03 15:59:27 +00:00
|
|
|
default:
|
2022-03-12 00:44:52 +00:00
|
|
|
return getEnterpriseResourceIter(context, aclObj, namespace, prefix, ws, store)
|
2017-08-03 15:59:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
// wildcard is a helper for determining if namespace is '*', used to determine
|
|
|
|
// if objects from every namespace should be considered when iterating, and that
|
|
|
|
// additional ACL checks will be necessary.
|
|
|
|
func wildcard(namespace string) bool {
|
|
|
|
return namespace == structs.AllNamespacesSentinel
|
|
|
|
}
|
|
|
|
|
2022-03-09 01:54:17 +00:00
|
|
|
func getFuzzyResourceIterator(context structs.Context, aclObj *acl.ACL, namespace string, ws memdb.WatchSet, store *state.StateStore) (memdb.ResultIterator, error) {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
switch context {
|
|
|
|
case structs.Jobs:
|
|
|
|
if wildcard(namespace) {
|
2022-03-09 01:54:17 +00:00
|
|
|
iter, err := store.Jobs(ws)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
return nsCapIterFilter(iter, err, aclObj)
|
|
|
|
}
|
2022-03-09 01:54:17 +00:00
|
|
|
return store.JobsByNamespace(ws, namespace)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
|
|
|
|
case structs.Allocs:
|
|
|
|
if wildcard(namespace) {
|
2022-03-09 01:54:17 +00:00
|
|
|
iter, err := store.Allocs(ws, state.SortDefault)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
return nsCapIterFilter(iter, err, aclObj)
|
|
|
|
}
|
2022-03-09 01:54:17 +00:00
|
|
|
return store.AllocsByNamespace(ws, namespace)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
|
2022-06-20 03:39:00 +00:00
|
|
|
case structs.SecureVariables:
|
|
|
|
if wildcard(namespace) {
|
|
|
|
iter, err := store.SecureVariables(ws)
|
|
|
|
return nsCapIterFilter(iter, err, aclObj)
|
|
|
|
}
|
|
|
|
return store.GetSecureVariablesByNamespace(ws, namespace)
|
|
|
|
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
case structs.Nodes:
|
|
|
|
if wildcard(namespace) {
|
2022-03-09 01:54:17 +00:00
|
|
|
iter, err := store.Nodes(ws)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
return nsCapIterFilter(iter, err, aclObj)
|
|
|
|
}
|
2022-03-09 01:54:17 +00:00
|
|
|
return store.Nodes(ws)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
|
|
|
|
case structs.Plugins:
|
|
|
|
if wildcard(namespace) {
|
2022-03-09 01:54:17 +00:00
|
|
|
iter, err := store.CSIPlugins(ws)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
return nsCapIterFilter(iter, err, aclObj)
|
|
|
|
}
|
2022-03-09 01:54:17 +00:00
|
|
|
return store.CSIPlugins(ws)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
|
|
|
|
case structs.Namespaces:
|
2022-03-09 01:54:17 +00:00
|
|
|
iter, err := store.Namespaces(ws)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
return nsCapIterFilter(iter, err, aclObj)
|
|
|
|
|
|
|
|
default:
|
2022-03-09 01:54:17 +00:00
|
|
|
return getEnterpriseFuzzyResourceIter(context, aclObj, namespace, ws, store)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsCapIterFilter wraps an iterator with a filter for removing items that the token
|
|
|
|
// does not have permission to read (whether missing the capability or in the
|
|
|
|
// wrong namespace).
|
|
|
|
func nsCapIterFilter(iter memdb.ResultIterator, err error, aclObj *acl.ACL) (memdb.ResultIterator, error) {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if aclObj == nil {
|
|
|
|
return iter, nil
|
|
|
|
}
|
|
|
|
return memdb.NewFilterIterator(iter, nsCapFilter(aclObj)), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsCapFilter produces a memdb.FilterFunc for removing objects not accessible
|
|
|
|
// by aclObj during a table scan.
|
|
|
|
func nsCapFilter(aclObj *acl.ACL) memdb.FilterFunc {
|
2020-10-21 04:16:25 +00:00
|
|
|
return func(v interface{}) bool {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
switch t := v.(type) {
|
|
|
|
case *structs.Job:
|
|
|
|
return !aclObj.AllowNsOp(t.Namespace, acl.NamespaceCapabilityReadJob)
|
|
|
|
|
|
|
|
case *structs.Allocation:
|
|
|
|
return !aclObj.AllowNsOp(t.Namespace, acl.NamespaceCapabilityReadJob)
|
|
|
|
|
2022-06-20 03:39:00 +00:00
|
|
|
case *structs.SecureVariableEncrypted:
|
|
|
|
// FIXME: Update to final implementation.
|
|
|
|
return !aclObj.AllowNsOp(t.Namespace, acl.NamespaceCapabilityReadJob)
|
|
|
|
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
case *structs.Namespace:
|
|
|
|
return !aclObj.AllowNamespace(t.Name)
|
|
|
|
|
|
|
|
case *structs.Node:
|
|
|
|
return !aclObj.AllowNodeRead()
|
|
|
|
|
|
|
|
case *structs.CSIPlugin:
|
|
|
|
return !aclObj.AllowPluginRead()
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
2020-10-21 04:16:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-10 14:48:02 +00:00
|
|
|
// If the length of a prefix is odd, return a subset to the last even character
|
2017-08-11 13:33:12 +00:00
|
|
|
// This only applies to UUIDs, jobs are excluded
|
2017-08-14 13:34:31 +00:00
|
|
|
func roundUUIDDownIfOdd(prefix string, context structs.Context) string {
|
|
|
|
if context == structs.Jobs {
|
2017-08-10 14:48:02 +00:00
|
|
|
return prefix
|
|
|
|
}
|
|
|
|
|
2017-08-29 16:21:18 +00:00
|
|
|
// We ignore the count of hyphens when calculating if the prefix is even:
|
|
|
|
// E.g "e3671fa4-21"
|
|
|
|
numHyphens := strings.Count(prefix, "-")
|
|
|
|
l := len(prefix) - numHyphens
|
2017-08-11 13:33:12 +00:00
|
|
|
if l%2 == 0 {
|
2017-08-10 14:48:02 +00:00
|
|
|
return prefix
|
2017-08-08 20:29:02 +00:00
|
|
|
}
|
2017-09-13 17:28:42 +00:00
|
|
|
return prefix[:len(prefix)-1]
|
2017-08-08 20:29:02 +00:00
|
|
|
}
|
|
|
|
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
// silenceError determines whether err is an error we care about when getting an
|
|
|
|
// iterator from the state store - we ignore errors about invalid UUIDs, since
|
|
|
|
// we sometimes try to lookup by Name and not UUID.
|
|
|
|
func (*Search) silenceError(err error) bool {
|
|
|
|
if err == nil {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
e := err.Error()
|
|
|
|
switch {
|
|
|
|
// Searching other contexts with job names raises an error, which in
|
|
|
|
// this case we want to ignore.
|
|
|
|
case strings.Contains(e, "Invalid UUID: encoding/hex"):
|
|
|
|
case strings.Contains(e, "UUID have 36 characters"):
|
|
|
|
case strings.Contains(e, "must be even length"):
|
|
|
|
case strings.Contains(e, "UUID should have maximum of 4"):
|
|
|
|
default:
|
|
|
|
// err was not nil and not about UUID prefix, something bad happened
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2017-08-11 14:44:46 +00:00
|
|
|
// PrefixSearch is used to list matches for a given prefix, and returns
|
|
|
|
// matching jobs, evaluations, allocations, and/or nodes.
|
2017-10-10 22:04:23 +00:00
|
|
|
func (s *Search) PrefixSearch(args *structs.SearchRequest, reply *structs.SearchResponse) error {
|
2017-12-20 20:17:28 +00:00
|
|
|
if done, err := s.srv.forward("Search.PrefixSearch", args, args, reply); done {
|
|
|
|
return err
|
|
|
|
}
|
2017-12-20 22:52:41 +00:00
|
|
|
defer metrics.MeasureSince([]string{"nomad", "search", "prefix_search"}, time.Now())
|
2017-12-20 20:17:28 +00:00
|
|
|
|
2017-10-12 22:16:33 +00:00
|
|
|
aclObj, err := s.srv.ResolveToken(args.AuthToken)
|
2017-10-10 22:04:23 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-10-12 01:05:27 +00:00
|
|
|
namespace := args.RequestNamespace()
|
2017-10-10 22:04:23 +00:00
|
|
|
|
2022-07-21 12:39:36 +00:00
|
|
|
// Require read permissions for the context, ex. node:read or
|
|
|
|
// namespace:read-job
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
if !sufficientSearchPerms(aclObj, namespace, args.Context) {
|
2017-10-12 01:05:27 +00:00
|
|
|
return structs.ErrPermissionDenied
|
2017-10-10 22:04:23 +00:00
|
|
|
}
|
|
|
|
|
2017-08-14 13:34:31 +00:00
|
|
|
reply.Matches = make(map[structs.Context][]string)
|
|
|
|
reply.Truncations = make(map[structs.Context]bool)
|
2017-07-28 21:48:15 +00:00
|
|
|
|
|
|
|
// Setup the blocking query
|
|
|
|
opts := blockingOptions{
|
|
|
|
queryMeta: &reply.QueryMeta,
|
2017-08-14 13:34:31 +00:00
|
|
|
queryOpts: &structs.QueryOptions{},
|
2017-07-28 21:48:15 +00:00
|
|
|
run: func(ws memdb.WatchSet, state *state.StateStore) error {
|
|
|
|
|
2017-08-14 13:34:31 +00:00
|
|
|
iters := make(map[structs.Context]memdb.ResultIterator)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
contexts := filteredSearchContexts(aclObj, namespace, args.Context)
|
2017-08-04 22:18:49 +00:00
|
|
|
|
2017-08-14 13:34:31 +00:00
|
|
|
for _, ctx := range contexts {
|
2017-10-13 21:36:02 +00:00
|
|
|
iter, err := getResourceIter(ctx, aclObj, namespace, roundUUIDDownIfOdd(args.Prefix, args.Context), ws, state)
|
2017-08-03 15:59:27 +00:00
|
|
|
if err != nil {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
if !s.silenceError(err) {
|
2017-08-18 20:27:53 +00:00
|
|
|
return err
|
|
|
|
}
|
2017-08-15 17:43:50 +00:00
|
|
|
} else {
|
|
|
|
iters[ctx] = iter
|
2017-08-03 15:59:27 +00:00
|
|
|
}
|
2017-07-28 21:48:15 +00:00
|
|
|
}
|
|
|
|
|
2017-08-04 14:18:46 +00:00
|
|
|
// Return matches for the given prefix
|
2017-08-03 15:59:27 +00:00
|
|
|
for k, v := range iters {
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
res, isTrunc := s.getPrefixMatches(v, args.Prefix)
|
2017-08-03 15:59:27 +00:00
|
|
|
reply.Matches[k] = res
|
|
|
|
reply.Truncations[k] = isTrunc
|
2017-08-02 21:55:48 +00:00
|
|
|
}
|
2017-08-03 14:28:38 +00:00
|
|
|
|
2017-08-04 15:08:12 +00:00
|
|
|
// Set the index for the context. If the context has been specified, it
|
2017-08-07 15:07:18 +00:00
|
|
|
// will be used as the index of the response. Otherwise, the
|
|
|
|
// maximum index from all resources will be used.
|
2017-08-14 13:34:31 +00:00
|
|
|
for _, ctx := range contexts {
|
2017-10-13 21:36:02 +00:00
|
|
|
index, err := state.Index(contextToIndex(ctx))
|
2017-08-07 15:07:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if index > reply.Index {
|
|
|
|
reply.Index = index
|
2017-08-03 22:39:56 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-03 15:12:14 +00:00
|
|
|
|
2017-08-10 19:24:11 +00:00
|
|
|
s.srv.setQueryMeta(&reply.QueryMeta)
|
2017-07-28 21:48:15 +00:00
|
|
|
return nil
|
|
|
|
}}
|
2017-08-10 19:24:11 +00:00
|
|
|
return s.srv.blockingRPC(&opts)
|
2017-07-28 21:48:15 +00:00
|
|
|
}
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
|
2022-07-14 15:31:08 +00:00
|
|
|
// sufficientSearchPerms returns true if the provided ACL has access to any
|
|
|
|
// capabilities required for prefix searching.
|
|
|
|
//
|
|
|
|
// Returns true if aclObj is nil or is for a management token
|
|
|
|
func sufficientSearchPerms(aclObj *acl.ACL, namespace string, context structs.Context) bool {
|
|
|
|
if aclObj == nil || aclObj.IsManagement() {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
nodeRead := aclObj.AllowNodeRead()
|
|
|
|
allowNS := aclObj.AllowNamespace(namespace)
|
|
|
|
jobRead := aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityReadJob)
|
|
|
|
allowEnt := sufficientSearchPermsEnt(aclObj)
|
|
|
|
|
|
|
|
if !nodeRead && !allowNS && !allowEnt && !jobRead {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reject requests that explicitly specify a disallowed context. This
|
|
|
|
// should give the user better feedback than simply filtering out all
|
|
|
|
// results and returning an empty list.
|
|
|
|
switch context {
|
|
|
|
case structs.Nodes:
|
|
|
|
return nodeRead
|
|
|
|
case structs.Namespaces:
|
|
|
|
return allowNS
|
|
|
|
case structs.Allocs, structs.Deployments, structs.Evals, structs.Jobs:
|
|
|
|
return jobRead
|
|
|
|
case structs.Volumes:
|
|
|
|
return acl.NamespaceValidator(acl.NamespaceCapabilityCSIListVolume,
|
|
|
|
acl.NamespaceCapabilityCSIReadVolume,
|
|
|
|
acl.NamespaceCapabilityListJobs,
|
|
|
|
acl.NamespaceCapabilityReadJob)(aclObj, namespace)
|
|
|
|
case structs.SecureVariables:
|
2022-07-21 12:39:36 +00:00
|
|
|
return aclObj.AllowSecureVariableSearch(namespace)
|
2022-07-14 15:31:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
// FuzzySearch is used to list fuzzy or prefix matches for a given text argument and Context.
|
|
|
|
// If the Context is "all", all searchable contexts are searched. If ACLs are enabled,
|
|
|
|
// results are limited to policies of the provided ACL token.
|
|
|
|
//
|
|
|
|
// These types are limited to prefix UUID searching:
|
|
|
|
// Evals, Deployments, ScalingPolicies, Volumes
|
|
|
|
//
|
|
|
|
// These types are available for fuzzy searching:
|
|
|
|
// Nodes, Namespaces, Jobs, Allocs, Plugins
|
|
|
|
//
|
|
|
|
// Jobs are a special case that expand into multiple types, and whose return
|
|
|
|
// values include Scope which is a descending list of IDs of parent objects,
|
|
|
|
// starting with the Namespace. The subtypes of jobs are fuzzy searchable.
|
|
|
|
//
|
|
|
|
// The Jobs type expands into these sub types:
|
|
|
|
// Jobs, Groups, Services, Tasks, Images, Commands, Classes
|
|
|
|
//
|
|
|
|
// The results are in descending order starting with strongest match, per Context type.
|
|
|
|
func (s *Search) FuzzySearch(args *structs.FuzzySearchRequest, reply *structs.FuzzySearchResponse) error {
|
|
|
|
if done, err := s.srv.forward("Search.FuzzySearch", args, args, reply); done {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer metrics.MeasureSince([]string{"nomad", "search", "fuzzy_search"}, time.Now())
|
|
|
|
|
|
|
|
aclObj, err := s.srv.ResolveToken(args.AuthToken)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace := args.RequestNamespace()
|
|
|
|
context := args.Context
|
|
|
|
|
|
|
|
if !sufficientFuzzySearchPerms(aclObj, namespace, context) {
|
|
|
|
return structs.ErrPermissionDenied
|
|
|
|
}
|
|
|
|
|
|
|
|
// check that fuzzy search API is enabled
|
|
|
|
if !s.srv.config.SearchConfig.FuzzyEnabled {
|
|
|
|
return fmt.Errorf("fuzzy search is not enabled")
|
|
|
|
}
|
|
|
|
|
|
|
|
// check the query term meets minimum length
|
|
|
|
min := s.srv.config.SearchConfig.MinTermLength
|
|
|
|
if n := len(args.Text); n < min {
|
|
|
|
return fmt.Errorf("fuzzy search query must be at least %d characters, got %d", min, n)
|
|
|
|
}
|
|
|
|
|
2021-04-16 22:56:03 +00:00
|
|
|
// for case-insensitive searching, lower-case the search term once and reuse
|
|
|
|
text := strings.ToLower(args.Text)
|
|
|
|
|
|
|
|
// accumulate fuzzy search results and any truncations
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
reply.Matches = make(map[structs.Context][]structs.FuzzyMatch)
|
|
|
|
reply.Truncations = make(map[structs.Context]bool)
|
|
|
|
|
|
|
|
// Setup the blocking query
|
|
|
|
opts := blockingOptions{
|
|
|
|
queryMeta: &reply.QueryMeta,
|
|
|
|
queryOpts: new(structs.QueryOptions),
|
|
|
|
run: func(ws memdb.WatchSet, state *state.StateStore) error {
|
|
|
|
|
|
|
|
fuzzyIters := make(map[structs.Context]memdb.ResultIterator)
|
|
|
|
prefixIters := make(map[structs.Context]memdb.ResultIterator)
|
|
|
|
|
|
|
|
prefixContexts := filteredSearchContexts(aclObj, namespace, context)
|
|
|
|
fuzzyContexts := filteredFuzzySearchContexts(aclObj, namespace, context)
|
|
|
|
|
|
|
|
// Gather the iterators used for prefix searching from those allowable contexts
|
|
|
|
for _, ctx := range prefixContexts {
|
|
|
|
switch ctx {
|
|
|
|
// only apply on the types that use UUID prefix searching
|
2021-04-20 15:23:28 +00:00
|
|
|
case structs.Evals, structs.Deployments, structs.ScalingPolicies, structs.Volumes, structs.Quotas, structs.Recommendations:
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
iter, err := getResourceIter(ctx, aclObj, namespace, roundUUIDDownIfOdd(args.Prefix, args.Context), ws, state)
|
|
|
|
if err != nil {
|
|
|
|
if !s.silenceError(err) {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
prefixIters[ctx] = iter
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gather the iterators used for fuzzy searching from those allowable contexts
|
|
|
|
for _, ctx := range fuzzyContexts {
|
|
|
|
switch ctx {
|
|
|
|
// skip the types that use UUID prefix searching
|
2021-04-20 15:23:28 +00:00
|
|
|
case structs.Evals, structs.Deployments, structs.ScalingPolicies, structs.Volumes, structs.Quotas, structs.Recommendations:
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
continue
|
|
|
|
default:
|
|
|
|
iter, err := getFuzzyResourceIterator(ctx, aclObj, namespace, ws, state)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
fuzzyIters[ctx] = iter
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set prefix matches of the given text
|
|
|
|
for ctx, iter := range prefixIters {
|
|
|
|
res, isTrunc := s.getPrefixMatches(iter, args.Text)
|
|
|
|
matches := make([]structs.FuzzyMatch, 0, len(res))
|
|
|
|
for _, result := range res {
|
|
|
|
matches = append(matches, structs.FuzzyMatch{ID: result})
|
|
|
|
}
|
|
|
|
reply.Matches[ctx] = matches
|
|
|
|
reply.Truncations[ctx] = isTrunc
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set fuzzy matches of the given text
|
|
|
|
for iterCtx, iter := range fuzzyIters {
|
|
|
|
|
|
|
|
// prefill truncations of iterable types so keys will exist in
|
|
|
|
// the response for negative results
|
|
|
|
reply.Truncations[iterCtx] = false
|
|
|
|
|
2021-04-16 22:56:03 +00:00
|
|
|
matches, truncations := s.getFuzzyMatches(iter, text)
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
for ctx := range matches {
|
|
|
|
reply.Matches[ctx] = matches[ctx]
|
|
|
|
}
|
|
|
|
|
|
|
|
for ctx := range truncations {
|
|
|
|
// only contains positive results
|
|
|
|
reply.Truncations[ctx] = truncations[ctx]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the index for the context. If the context has been specified,
|
|
|
|
// it will be used as the index of the response. Otherwise, the maximum
|
|
|
|
// index from all the resources will be used.
|
|
|
|
for _, ctx := range fuzzyContexts {
|
|
|
|
index, err := state.Index(contextToIndex(ctx))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if index > reply.Index {
|
|
|
|
reply.Index = index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
s.srv.setQueryMeta(&reply.QueryMeta)
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return s.srv.blockingRPC(&opts)
|
|
|
|
}
|
|
|
|
|
|
|
|
// expandContext returns either allContexts if context is 'all', or a one
|
|
|
|
// element slice with context by itself.
|
|
|
|
func expandContext(context structs.Context) []structs.Context {
|
|
|
|
switch context {
|
|
|
|
case structs.All:
|
|
|
|
c := make([]structs.Context, len(allContexts))
|
|
|
|
copy(c, allContexts)
|
|
|
|
return c
|
|
|
|
default:
|
|
|
|
return []structs.Context{context}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// sufficientFuzzySearchPerms returns true if the searched namespace is the wildcard
|
|
|
|
// namespace, indicating we should bypass the preflight ACL checks otherwise performed
|
|
|
|
// by sufficientSearchPerms. This is to support fuzzy searching multiple namespaces
|
|
|
|
// with tokens that have permission for more than one namespace. The actual ACL
|
|
|
|
// validation will be performed while scanning objects instead, where we have finally
|
|
|
|
// have a concrete namespace to work with.
|
|
|
|
func sufficientFuzzySearchPerms(aclObj *acl.ACL, namespace string, context structs.Context) bool {
|
|
|
|
if wildcard(namespace) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return sufficientSearchPerms(aclObj, namespace, context)
|
|
|
|
}
|
|
|
|
|
2022-07-14 15:31:08 +00:00
|
|
|
// filteredSearchContexts returns the expanded set of contexts, filtered down
|
|
|
|
// to the subset of contexts the aclObj is valid for.
|
|
|
|
//
|
|
|
|
// If aclObj is nil, no contexts are filtered out.
|
|
|
|
func filteredSearchContexts(aclObj *acl.ACL, namespace string, context structs.Context) []structs.Context {
|
|
|
|
desired := expandContext(context)
|
|
|
|
|
|
|
|
// If ACLs aren't enabled return all contexts
|
|
|
|
if aclObj == nil {
|
|
|
|
return desired
|
|
|
|
}
|
|
|
|
if aclObj.IsManagement() {
|
|
|
|
return desired
|
|
|
|
}
|
|
|
|
jobRead := aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityReadJob)
|
|
|
|
allowVolume := acl.NamespaceValidator(acl.NamespaceCapabilityCSIListVolume,
|
|
|
|
acl.NamespaceCapabilityCSIReadVolume,
|
|
|
|
acl.NamespaceCapabilityListJobs,
|
|
|
|
acl.NamespaceCapabilityReadJob)
|
|
|
|
volRead := allowVolume(aclObj, namespace)
|
|
|
|
policyRead := aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityListScalingPolicies)
|
|
|
|
|
|
|
|
// Filter contexts down to those the ACL grants access to
|
|
|
|
available := make([]structs.Context, 0, len(desired))
|
|
|
|
for _, c := range desired {
|
|
|
|
switch c {
|
|
|
|
case structs.Allocs, structs.Jobs, structs.Evals, structs.Deployments:
|
|
|
|
if jobRead {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
|
|
|
case structs.ScalingPolicies:
|
|
|
|
if policyRead || jobRead {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
|
|
|
case structs.Namespaces:
|
|
|
|
if aclObj.AllowNamespace(namespace) {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
|
|
|
case structs.SecureVariables:
|
|
|
|
if jobRead {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
|
|
|
case structs.Nodes:
|
|
|
|
if aclObj.AllowNodeRead() {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
|
|
|
case structs.Volumes:
|
|
|
|
if volRead {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if ok := filteredSearchContextsEnt(aclObj, namespace, c); ok {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return available
|
|
|
|
}
|
|
|
|
|
api: implement fuzzy search API
This PR introduces the /v1/search/fuzzy API endpoint, used for fuzzy
searching objects in Nomad. The fuzzy search endpoint routes requests
to the Nomad Server leader, which implements the Search.FuzzySearch RPC
method.
Requests to the fuzzy search API are based on the api.FuzzySearchRequest
object, e.g.
{
"Text": "ed",
"Context": "all"
}
Responses from the fuzzy search API are based on the api.FuzzySearchResponse
object, e.g.
{
"Index": 27,
"KnownLeader": true,
"LastContact": 0,
"Matches": {
"tasks": [
{
"ID": "redis",
"Scope": [
"default",
"example",
"cache"
]
}
],
"evals": [],
"deployment": [],
"volumes": [],
"scaling_policy": [],
"images": [
{
"ID": "redis:3.2",
"Scope": [
"default",
"example",
"cache",
"redis"
]
}
]
},
"Truncations": {
"volumes": false,
"scaling_policy": false,
"evals": false,
"deployment": false
}
}
The API is tunable using the new server.search stanza, e.g.
server {
search {
fuzzy_enabled = true
limit_query = 200
limit_results = 1000
min_term_length = 5
}
}
These values can be increased or decreased, so as to provide more
search results or to reduce load on the Nomad Server. The fuzzy search
API can be disabled entirely by setting `fuzzy_enabled` to `false`.
2021-02-23 20:24:52 +00:00
|
|
|
// filterFuzzySearchContexts returns every context asked for if the searched namespace
|
|
|
|
// is the wildcard namespace, indicating we should bypass ACL checks otherwise
|
|
|
|
// performed by filterSearchContexts. Instead we will rely on iterator filters to
|
|
|
|
// perform the ACL validation while scanning objects, where we have a concrete
|
|
|
|
// namespace to work with.
|
|
|
|
func filteredFuzzySearchContexts(aclObj *acl.ACL, namespace string, context structs.Context) []structs.Context {
|
|
|
|
if wildcard(namespace) {
|
|
|
|
return expandContext(context)
|
|
|
|
}
|
|
|
|
return filteredSearchContexts(aclObj, namespace, context)
|
|
|
|
}
|