2020-02-10 20:56:14 +00:00
|
|
|
// +build !ent
|
2017-09-07 23:56:15 +00:00
|
|
|
|
|
|
|
package nomad
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
memdb "github.com/hashicorp/go-memdb"
|
2017-10-12 01:05:27 +00:00
|
|
|
"github.com/hashicorp/nomad/acl"
|
2017-09-07 23:56:15 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/state"
|
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
|
|
)
|
|
|
|
|
2017-09-08 00:13:18 +00:00
|
|
|
var (
|
|
|
|
// allContexts are the available contexts which are searched to find matches
|
|
|
|
// for a given prefix
|
|
|
|
allContexts = ossContexts
|
|
|
|
)
|
|
|
|
|
2017-10-13 21:36:02 +00:00
|
|
|
// contextToIndex returns the index name to lookup in the state store.
|
|
|
|
func contextToIndex(ctx structs.Context) string {
|
|
|
|
return string(ctx)
|
|
|
|
}
|
|
|
|
|
2017-09-07 23:56:15 +00:00
|
|
|
// getEnterpriseMatch is a no-op in oss since there are no enterprise objects.
|
|
|
|
func getEnterpriseMatch(match interface{}) (id string, ok bool) {
|
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
|
|
|
|
// getEnterpriseResourceIter is used to retrieve an iterator over an enterprise
|
|
|
|
// only table.
|
2017-10-13 21:36:02 +00:00
|
|
|
func getEnterpriseResourceIter(context structs.Context, _ *acl.ACL, namespace, prefix string, ws memdb.WatchSet, state *state.StateStore) (memdb.ResultIterator, error) {
|
2017-09-07 23:56:15 +00:00
|
|
|
// If we have made it here then it is an error since we have exhausted all
|
|
|
|
// open source contexts.
|
2017-09-08 00:13:18 +00:00
|
|
|
return nil, fmt.Errorf("context must be one of %v or 'all' for all contexts; got %q", allContexts, context)
|
2017-09-07 23:56:15 +00:00
|
|
|
}
|
2017-10-12 01:05: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
|
|
|
// getEnterpriseFuzzyResourceIter is used to retrieve an iterator over an enterprise
|
|
|
|
// only table.
|
|
|
|
func getEnterpriseFuzzyResourceIter(context structs.Context, _ *acl.ACL, _ string, _ memdb.WatchSet, _ *state.StateStore) (memdb.ResultIterator, error) {
|
|
|
|
return nil, fmt.Errorf("context must be one of %v or 'all' for all contexts; got %q", allContexts, context)
|
|
|
|
}
|
|
|
|
|
|
|
|
// sufficientSearchPerms returns true if the provided ACL has access to each
|
|
|
|
// capability required for prefix searching for the given context.
|
|
|
|
//
|
|
|
|
// Returns true if aclObj is nil.
|
|
|
|
func sufficientSearchPerms(aclObj *acl.ACL, namespace string, context structs.Context) bool {
|
2017-10-12 01:05:27 +00:00
|
|
|
if aclObj == nil {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
nodeRead := aclObj.AllowNodeRead()
|
2020-10-21 04:16:25 +00:00
|
|
|
allowNS := aclObj.AllowNamespace(namespace)
|
2017-10-12 01:05:27 +00:00
|
|
|
jobRead := aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityReadJob)
|
2020-03-17 21:32:39 +00:00
|
|
|
allowVolume := acl.NamespaceValidator(acl.NamespaceCapabilityCSIListVolume,
|
|
|
|
acl.NamespaceCapabilityCSIReadVolume,
|
|
|
|
acl.NamespaceCapabilityListJobs,
|
|
|
|
acl.NamespaceCapabilityReadJob)
|
|
|
|
volRead := allowVolume(aclObj, namespace)
|
|
|
|
|
2020-10-21 04:16:25 +00:00
|
|
|
if !nodeRead && !jobRead && !volRead && !allowNS {
|
2017-10-12 01:05:27 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reject requests that explicitly specify a disallowed context. This
|
|
|
|
// should give the user better feedback then simply filtering out all
|
|
|
|
// results and returning an empty list.
|
|
|
|
if !nodeRead && context == structs.Nodes {
|
|
|
|
return false
|
|
|
|
}
|
2020-10-21 04:16:25 +00:00
|
|
|
if !allowNS && context == structs.Namespaces {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-10-12 01:05:27 +00:00
|
|
|
if !jobRead {
|
|
|
|
switch context {
|
|
|
|
case structs.Allocs, structs.Deployments, structs.Evals, structs.Jobs:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2020-03-17 21:32:39 +00:00
|
|
|
if !volRead && context == structs.Volumes {
|
|
|
|
return false
|
|
|
|
}
|
2017-10-12 01:05:27 +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
|
|
|
// 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)
|
2017-10-12 01:05:27 +00:00
|
|
|
|
|
|
|
// If ACLs aren't enabled return all contexts
|
|
|
|
if aclObj == 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 desired
|
2017-10-12 01:05:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jobRead := aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityReadJob)
|
2020-03-17 21:32:39 +00:00
|
|
|
allowVolume := acl.NamespaceValidator(acl.NamespaceCapabilityCSIListVolume,
|
|
|
|
acl.NamespaceCapabilityCSIReadVolume,
|
|
|
|
acl.NamespaceCapabilityListJobs,
|
|
|
|
acl.NamespaceCapabilityReadJob)
|
|
|
|
volRead := allowVolume(aclObj, namespace)
|
2021-02-03 19:26:57 +00:00
|
|
|
policyRead := aclObj.AllowNsOp(namespace, acl.NamespaceCapabilityListScalingPolicies)
|
2017-10-12 01:05:27 +00:00
|
|
|
|
|
|
|
// Filter contexts down to those the ACL grants access to
|
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
|
|
|
available := make([]structs.Context, 0, len(desired))
|
|
|
|
for _, c := range desired {
|
2017-10-12 01:05:27 +00:00
|
|
|
switch c {
|
|
|
|
case structs.Allocs, structs.Jobs, structs.Evals, structs.Deployments:
|
|
|
|
if jobRead {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
2021-02-03 19:26:57 +00:00
|
|
|
case structs.ScalingPolicies:
|
|
|
|
if policyRead || jobRead {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
2020-10-21 04:16:25 +00:00
|
|
|
case structs.Namespaces:
|
|
|
|
if aclObj.AllowNamespace(namespace) {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
2017-10-12 01:05:27 +00:00
|
|
|
case structs.Nodes:
|
|
|
|
if aclObj.AllowNodeRead() {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
2020-03-17 21:32:39 +00:00
|
|
|
case structs.Volumes:
|
|
|
|
if volRead {
|
|
|
|
available = append(available, c)
|
|
|
|
}
|
2017-10-12 01:05:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return available
|
|
|
|
}
|