Update go-bexpr (#6190)

* Update go-bexpr to v0.1.1

This brings in:

• `in`/`not in` operators to do substring matching
• `matches` / `not matches` operators to perform regex string matching.

* Add the capability to auto-generate the filtering selector ops tables for our docs
This commit is contained in:
Matt Keeler 2019-07-23 14:45:20 -04:00 committed by GitHub
parent a4431da1cc
commit d7fe8befa9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 793 additions and 556 deletions

View File

@ -1,7 +1,12 @@
package structs
import (
"flag"
"fmt"
"os"
"sort"
"strings"
"sync"
"testing"
"github.com/hashicorp/consul/api"
@ -10,7 +15,7 @@ import (
"github.com/stretchr/testify/require"
)
const dumpFieldConfig bool = false
var dumpFieldConfig = flag.Bool("dump-field-config", false, "generate field config dump file")
///////////////////////////////////////////////////////////////////////////////
//
@ -27,11 +32,31 @@ type fieldConfigTest struct {
expected bexpr.FieldConfigurations
}
// ----------------------------------------------------------------------------
//
// The following are not explicitly tested as they are supporting structures
// nested within the other API responses
//
// ----------------------------------------------------------------------------
var expectedFieldConfigServiceAddress bexpr.FieldConfigurations = bexpr.FieldConfigurations{
"Address": &bexpr.FieldConfiguration{
StructFieldName: "Address",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Port": &bexpr.FieldConfiguration{
StructFieldName: "Port",
CoerceFn: bexpr.CoerceInt,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
},
}
var expectedFieldConfigMeshGatewayConfig bexpr.FieldConfigurations = bexpr.FieldConfigurations{
"Mode": &bexpr.FieldConfiguration{
StructFieldName: "Mode",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
}
@ -39,27 +64,27 @@ var expectedFieldConfigUpstreams bexpr.FieldConfigurations = bexpr.FieldConfigur
"DestinationType": &bexpr.FieldConfiguration{
StructFieldName: "DestinationType",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"DestinationNamespace": &bexpr.FieldConfiguration{
StructFieldName: "DestinationNamespace",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"DestinationName": &bexpr.FieldConfiguration{
StructFieldName: "DestinationName",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Datacenter": &bexpr.FieldConfiguration{
StructFieldName: "Datacenter",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"LocalBindAddress": &bexpr.FieldConfiguration{
StructFieldName: "LocalBindAddress",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"LocalBindPort": &bexpr.FieldConfiguration{
StructFieldName: "LocalBindPort",
@ -76,17 +101,17 @@ var expectedFieldConfigConnectProxyConfig bexpr.FieldConfigurations = bexpr.Fiel
"DestinationServiceName": &bexpr.FieldConfiguration{
StructFieldName: "DestinationServiceName",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"DestinationServiceID": &bexpr.FieldConfiguration{
StructFieldName: "DestinationServiceID",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"LocalServiceAddress": &bexpr.FieldConfiguration{
StructFieldName: "LocalServiceAddress",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"LocalServicePort": &bexpr.FieldConfiguration{
StructFieldName: "LocalServicePort",
@ -128,31 +153,43 @@ var expectedFieldConfigWeights bexpr.FieldConfigurations = bexpr.FieldConfigurat
var expectedFieldConfigMapStringValue bexpr.FieldConfigurations = bexpr.FieldConfigurations{
bexpr.FieldNameAny: &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
}
// these are not all in a table because some of them reference each other
var expectedFieldConfigMapStringServiceAddress bexpr.FieldConfigurations = bexpr.FieldConfigurations{
bexpr.FieldNameAny: &bexpr.FieldConfiguration{
SubFields: expectedFieldConfigServiceAddress,
},
}
// ----------------------------------------------------------------------------
//
// The following structures are within the test table as they are structures
// that will be sent back at the top level of API responses
//
// ----------------------------------------------------------------------------
var expectedFieldConfigNode bexpr.FieldConfigurations = bexpr.FieldConfigurations{
"ID": &bexpr.FieldConfiguration{
StructFieldName: "ID",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Node": &bexpr.FieldConfiguration{
StructFieldName: "Node",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Address": &bexpr.FieldConfiguration{
StructFieldName: "Address",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Datacenter": &bexpr.FieldConfiguration{
StructFieldName: "Datacenter",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"TaggedAddresses": &bexpr.FieldConfiguration{
StructFieldName: "TaggedAddresses",
@ -161,7 +198,7 @@ var expectedFieldConfigNode bexpr.FieldConfigurations = bexpr.FieldConfiguration
SubFields: bexpr.FieldConfigurations{
bexpr.FieldNameAny: &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
},
},
@ -172,40 +209,27 @@ var expectedFieldConfigNode bexpr.FieldConfigurations = bexpr.FieldConfiguration
SubFields: bexpr.FieldConfigurations{
bexpr.FieldNameAny: &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
},
},
}
var expectedFieldConfigMapStringServiceAddress bexpr.FieldConfigurations = bexpr.FieldConfigurations{
"Address": &bexpr.FieldConfiguration{
StructFieldName: "Address",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
},
"Port": &bexpr.FieldConfiguration{
StructFieldName: "Port",
CoerceFn: bexpr.CoerceInt,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
},
}
var expectedFieldConfigNodeService bexpr.FieldConfigurations = bexpr.FieldConfigurations{
"Kind": &bexpr.FieldConfiguration{
StructFieldName: "Kind",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"ID": &bexpr.FieldConfiguration{
StructFieldName: "ID",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Service": &bexpr.FieldConfiguration{
StructFieldName: "Service",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Tags": &bexpr.FieldConfiguration{
StructFieldName: "Tags",
@ -215,18 +239,14 @@ var expectedFieldConfigNodeService bexpr.FieldConfigurations = bexpr.FieldConfig
"Address": &bexpr.FieldConfiguration{
StructFieldName: "Address",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"TaggedAddresses": &bexpr.FieldConfiguration{
StructFieldName: "TaggedAddresses",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchIsEmpty, bexpr.MatchIsNotEmpty, bexpr.MatchIn, bexpr.MatchNotIn},
SubFields: bexpr.FieldConfigurations{
bexpr.FieldNameAny: &bexpr.FieldConfiguration{
SubFields: expectedFieldConfigMapStringServiceAddress,
},
},
},
"Meta": &bexpr.FieldConfiguration{
StructFieldName: "Meta",
CoerceFn: bexpr.CoerceString,
@ -261,22 +281,22 @@ var expectedFieldConfigServiceNode bexpr.FieldConfigurations = bexpr.FieldConfig
"ID": &bexpr.FieldConfiguration{
StructFieldName: "ID",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Node": &bexpr.FieldConfiguration{
StructFieldName: "Node",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Address": &bexpr.FieldConfiguration{
StructFieldName: "Address",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Datacenter": &bexpr.FieldConfiguration{
StructFieldName: "Datacenter",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"TaggedAddresses": &bexpr.FieldConfiguration{
StructFieldName: "TaggedAddresses",
@ -293,17 +313,17 @@ var expectedFieldConfigServiceNode bexpr.FieldConfigurations = bexpr.FieldConfig
"ServiceKind": &bexpr.FieldConfiguration{
StructFieldName: "ServiceKind",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"ServiceID": &bexpr.FieldConfiguration{
StructFieldName: "ServiceID",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"ServiceName": &bexpr.FieldConfiguration{
StructFieldName: "ServiceName",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"ServiceTags": &bexpr.FieldConfiguration{
StructFieldName: "ServiceTags",
@ -313,18 +333,14 @@ var expectedFieldConfigServiceNode bexpr.FieldConfigurations = bexpr.FieldConfig
"ServiceAddress": &bexpr.FieldConfiguration{
StructFieldName: "ServiceAddress",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"ServiceTaggedAddresses": &bexpr.FieldConfiguration{
StructFieldName: "ServiceTaggedAddresses",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchIsEmpty, bexpr.MatchIsNotEmpty, bexpr.MatchIn, bexpr.MatchNotIn},
SubFields: bexpr.FieldConfigurations{
bexpr.FieldNameAny: &bexpr.FieldConfiguration{
SubFields: expectedFieldConfigMapStringServiceAddress,
},
},
},
"ServiceMeta": &bexpr.FieldConfiguration{
StructFieldName: "ServiceMeta",
CoerceFn: bexpr.CoerceString,
@ -358,42 +374,42 @@ var expectedFieldConfigServiceNode bexpr.FieldConfigurations = bexpr.FieldConfig
var expectedFieldConfigHealthCheck bexpr.FieldConfigurations = bexpr.FieldConfigurations{
"Node": &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
StructFieldName: "Node",
},
"CheckId": &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
StructFieldName: "CheckId",
},
"Name": &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
StructFieldName: "Name",
},
"Status": &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
StructFieldName: "Status",
},
"Notes": &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
StructFieldName: "Notes",
},
"Output": &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
StructFieldName: "Output",
},
"ServiceID": &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
StructFieldName: "ServiceID",
},
"ServiceName": &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
StructFieldName: "ServiceName",
},
"ServiceTags": &bexpr.FieldConfiguration{
@ -423,39 +439,29 @@ var expectedFieldConfigNodeInfo bexpr.FieldConfigurations = bexpr.FieldConfigura
"ID": &bexpr.FieldConfiguration{
StructFieldName: "ID",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Node": &bexpr.FieldConfiguration{
StructFieldName: "Node",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"Address": &bexpr.FieldConfiguration{
StructFieldName: "Address",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
},
"TaggedAddresses": &bexpr.FieldConfiguration{
StructFieldName: "TaggedAddresses",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchIsEmpty, bexpr.MatchIsNotEmpty, bexpr.MatchIn, bexpr.MatchNotIn},
SubFields: bexpr.FieldConfigurations{
bexpr.FieldNameAny: &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
},
},
SubFields: expectedFieldConfigMapStringValue,
},
"Meta": &bexpr.FieldConfiguration{
StructFieldName: "Meta",
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchIsEmpty, bexpr.MatchIsNotEmpty, bexpr.MatchIn, bexpr.MatchNotIn},
SubFields: bexpr.FieldConfigurations{
bexpr.FieldNameAny: &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
},
},
SubFields: expectedFieldConfigMapStringValue,
},
"Services": &bexpr.FieldConfiguration{
StructFieldName: "Services",
@ -537,18 +543,93 @@ func validateFieldConfigurations(t *testing.T, expected, actual bexpr.FieldConfi
require.True(t, validateFieldConfigurationsRecurse(t, expected, actual, ""))
}
type fieldDumper struct {
fp *os.File
lock sync.Mutex
}
func newFieldDumper(t *testing.T, path string) *fieldDumper {
fp, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0660)
require.NoError(t, err)
return &fieldDumper{fp: fp}
}
func (d *fieldDumper) Close() {
d.fp.Close()
}
func (d *fieldDumper) DumpFields(name string, fields bexpr.FieldConfigurations) {
if d == nil {
return
}
selectorOps := make([][2]string, 0, 10)
// need at least 8 chars wide for "Selector"
maxSelectorLen := 8
// need at least 20 chars wid for "Supported Operaitons"
maxOpsLen := 20
fields.Walk(func(path bexpr.FieldPath, conf *bexpr.FieldConfiguration) bool {
if len(conf.SupportedOperations) < 1 {
return true
}
selector := path.String()
var ops []string
for _, op := range conf.SupportedOperations {
ops = append(ops, op.String())
}
opString := strings.Join(ops, ", ")
selLen := len(selector)
opsLen := len(opString)
if selLen > maxSelectorLen {
maxSelectorLen = selLen
}
if opsLen > maxOpsLen {
maxOpsLen = opsLen
}
selectorOps = append(selectorOps, [2]string{selector, opString})
return true
})
sort.Slice(selectorOps, func(i, j int) bool {
return selectorOps[i][0] < selectorOps[j][0]
})
d.lock.Lock()
defer d.lock.Unlock()
// this will print the header and the string form of the fields
fmt.Fprintf(d.fp, "===== %s =====\n%s\n\n", name, fields)
fmt.Fprintf(d.fp, "| %-[1]*[2]s | %-[3]*[4]s |\n", maxSelectorLen, "Selector", maxOpsLen, "Supported Operations")
fmt.Fprintf(d.fp, "| %s | %s |\n", strings.Repeat("-", maxSelectorLen), strings.Repeat("-", maxOpsLen))
for _, selOp := range selectorOps {
fmt.Fprintf(d.fp, "| %-[1]*[2]s | %-[3]*[4]s |\n", maxSelectorLen, selOp[0], maxOpsLen, selOp[1])
}
fmt.Fprintf(d.fp, "\n")
}
func TestStructs_FilterFieldConfigurations(t *testing.T) {
t.Parallel()
var d *fieldDumper
if *dumpFieldConfig {
d = newFieldDumper(t, "filter_fields.txt")
defer d.Close()
}
for name, tcase := range fieldConfigTests {
// capture these values in the closure
name := name
tcase := tcase
t.Run(name, func(t *testing.T) {
t.Parallel()
fields, err := bexpr.GenerateFieldConfigurations(tcase.dataType)
if dumpFieldConfig {
fmt.Printf("===== %s =====\n%s\n", name, fields)
}
d.DumpFields(name, fields)
require.NoError(t, err)
validateFieldConfigurations(t, tcase.expected, fields)
})

5
go.mod
View File

@ -41,7 +41,6 @@ require (
github.com/gocql/gocql v0.0.0-20180617115710-e06f8c1bcd78 // indirect
github.com/gogo/googleapis v1.1.0
github.com/gogo/protobuf v1.2.1
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7 // indirect
github.com/golang/protobuf v1.2.0
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
github.com/google/go-cmp v0.2.0 // indirect
@ -50,7 +49,7 @@ require (
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
github.com/hashicorp/consul/api v1.1.0
github.com/hashicorp/consul/sdk v0.1.1
github.com/hashicorp/go-bexpr v0.1.0
github.com/hashicorp/go-bexpr v0.1.2
github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de
github.com/hashicorp/go-cleanhttp v0.5.1
github.com/hashicorp/go-discover v0.0.0-20190403160810-22221edb15cd
@ -59,7 +58,6 @@ require (
github.com/hashicorp/go-msgpack v0.5.5
github.com/hashicorp/go-multierror v1.0.0
github.com/hashicorp/go-plugin v0.0.0-20180331002553-e8d22c780116
github.com/hashicorp/go-rootcerts v1.0.0
github.com/hashicorp/go-sockaddr v1.0.0
github.com/hashicorp/go-syslog v1.0.0
github.com/hashicorp/go-uuid v1.0.1
@ -83,7 +81,6 @@ require (
github.com/kr/pretty v0.1.0 // indirect
github.com/kr/text v0.1.0
github.com/lib/pq v0.0.0-20180523175426-90697d60dd84 // indirect
github.com/lyft/protoc-gen-validate v0.0.0-20180911180927-64fcb82c878e // indirect
github.com/miekg/dns v1.0.14
github.com/mitchellh/cli v1.0.0
github.com/mitchellh/copystructure v0.0.0-20160804032330-cdac8253d00f

46
go.sum
View File

@ -8,8 +8,6 @@ github.com/Azure/go-autorest v10.7.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSW
github.com/Azure/go-autorest v10.15.3+incompatible h1:nhKI/bvazIs3C3TFGoSqKY6hZ8f5od5mb5/UcS6HVIY=
github.com/Azure/go-autorest v10.15.3+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DataDog/datadog-go v0.0.0-20160329135253-cc2f4770f4d6 h1:veThyuVPIg0cAHly135Y+IW2ymFgZ1pftOyAVkqCoi8=
github.com/DataDog/datadog-go v0.0.0-20160329135253-cc2f4770f4d6/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/datadog-go v2.2.0+incompatible h1:V5BKkxACZLjzHjSgBbr2gvLA2Ae49yhc6CSY7MLy5k4=
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Jeffail/gabs v1.1.0 h1:kw5zCcl9tlJNHTDme7qbi21fDHZmXrnjMoXos3Jw/NI=
@ -52,12 +50,8 @@ github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY=
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/circonus-labs/circonus-gometrics v0.0.0-20161109192337-d17a8420c36e h1:VhMcRhkS/wJM+XfZxNn+tk5EVmF2k19g6yS6uDXHn0o=
github.com/circonus-labs/circonus-gometrics v0.0.0-20161109192337-d17a8420c36e/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.0.0-20161110002650-365d370cc145 h1:cwLvX6r5EOiVmkUYjY+Ev4ZJrkOhex3r+mfeqT8o+8c=
github.com/circonus-labs/circonusllhist v0.0.0-20161110002650-365d370cc145/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@ -86,8 +80,6 @@ github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 h1:2MIh
github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo=
github.com/elazarl/go-bindata-assetfs v0.0.0-20160803192304-e1a2a7ec64b0 h1:ZoRgc53qJCfSLimXqJDrmBhnt5GChDsExMCK7t48o0Y=
github.com/elazarl/go-bindata-assetfs v0.0.0-20160803192304-e1a2a7ec64b0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/envoyproxy/go-control-plane v0.0.0-20180919002855-2137d9196328 h1:kRYkA4bsDlXqE8xcdVkbtPOB93wyl7NHf790u9ck3ME=
github.com/envoyproxy/go-control-plane v0.0.0-20180919002855-2137d9196328/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.8.0 h1:uE6Fp4fOcAJdc1wTQXLJ+SYistkbG1dNoi6Zs1+Ybvk=
github.com/envoyproxy/go-control-plane v0.8.0/go.mod h1:GSSbY9P1neVhdY7G4wu+IK1rk/dqhiCC/4ExuWJZVuk=
github.com/envoyproxy/protoc-gen-validate v0.0.14 h1:YBW6/cKy9prEGRYLnaGa4IDhzxZhRCtKsax8srGKDnM=
@ -120,7 +112,6 @@ github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
@ -152,8 +143,10 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-bexpr v0.1.0 h1:hA/9CWGPsQ6YZXvPvizD+VEEjBG4V6Un0Qcyav5ghK4=
github.com/hashicorp/go-bexpr v0.1.0/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU=
github.com/hashicorp/go-bexpr v0.1.1 h1:WvjUsC7elNIAwpFGj7tfqXocJDBQbep0Py9hSNmtrFk=
github.com/hashicorp/go-bexpr v0.1.1/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU=
github.com/hashicorp/go-bexpr v0.1.2 h1:ijMXI4qERbzxbCnkxmfUtwMyjrrk3y+Vt0MxojNCbBs=
github.com/hashicorp/go-bexpr v0.1.2/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU=
github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de h1:XDCSythtg8aWSRSO29uwhgh7b127fWr+m5SemqjSUL8=
github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de/go.mod h1:xIwEieBHERyEvaeKF/TcHh1Hu+lxPM+n2vT1+g9I4m4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
@ -161,8 +154,6 @@ github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVo
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-discover v0.0.0-20190403160810-22221edb15cd h1:SynRxs8h2h7lLSA5py5a3WWkYpImhREtju0CuRd97wc=
github.com/hashicorp/go-discover v0.0.0-20190403160810-22221edb15cd/go.mod h1:ueUgD9BeIocT7QNuvxSyJyPAM9dfifBcaWmeybb67OY=
github.com/hashicorp/go-hclog v0.0.0-20180402200405-69ff559dc25f h1:t34t/ySFIGsPOLQ/dCcKeCoErlqhXlNLYvPn7mVogzo=
github.com/hashicorp/go-hclog v0.0.0-20180402200405-69ff559dc25f/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.9.1 h1:9PZfAcVEvez4yhLH2TBU64/h/z4xlFI80cWXRrxuKuM=
github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
@ -170,16 +161,12 @@ github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh
github.com/hashicorp/go-memdb v0.0.0-20180223233045-1289e7fffe71 h1:yxxFgVz31vFoKKTtRUNbXLNe4GFnbLKqg+0N7yG42L8=
github.com/hashicorp/go-memdb v0.0.0-20180223233045-1289e7fffe71/go.mod h1:kbfItVoBJwCfKXDXN4YoAXjxcFVZ7MRrJzyTX6H4giE=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-msgpack v0.5.4 h1:SFT72YqIkOcLdWJUYcriVX7hbrZpwc/f7h8aW2NUqrA=
github.com/hashicorp/go-msgpack v0.5.4/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI=
github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-plugin v0.0.0-20180331002553-e8d22c780116 h1:Y4V/yReWjQo/Ngyc0w6C3EKXKincp4YgvXeo8lI4LrI=
github.com/hashicorp/go-plugin v0.0.0-20180331002553-e8d22c780116/go.mod h1:JSqWYsict+jzcj0+xElxyrBQRPNoiWQuddnxArJ7XHQ=
github.com/hashicorp/go-retryablehttp v0.0.0-20180531211321-3b087ef2d313 h1:8YjGfJRRXO9DA6RG0wNt3kEkvvnxIDao5us1PG+S0wc=
github.com/hashicorp/go-retryablehttp v0.0.0-20180531211321-3b087ef2d313/go.mod h1:fXcdFsQoipQa7mwORhKad5jmDCeSy/RCGzWA08PO0lM=
github.com/hashicorp/go-retryablehttp v0.5.3 h1:QlWt0KvWT0lq8MFppF9tsJGF+ynG7ztc2KIPhzRGk7s=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI=
@ -210,14 +197,10 @@ github.com/hashicorp/mdns v1.0.1 h1:XFSOubp8KWB+Jd2PDyaX5xUd5bhSP/+pTDZVDMzZJM8=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/memberlist v0.1.4-0.20190515174901-e1138a6a4d8a h1:9V2hIf261IZE7KfJtTOAncg/BRrauZblzdyS9lrTl1E=
github.com/hashicorp/memberlist v0.1.4-0.20190515174901-e1138a6a4d8a/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/memberlist v0.1.4 h1:gkyML/r71w3FL8gUi74Vk76avkj/9lYAY9lvg0OcoGs=
github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 h1:lc3c72qGlIMDqQpQH82Y4vaglRMMFdJbziYWriR4UcE=
github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69/go.mod h1:/z+jUGRBlwVpUZfjute9jWaF6/HuhjuFQuL1YXzVD1Q=
github.com/hashicorp/raft v1.0.1-0.20190409200437-d9fe23f7d472 h1:9EPzHJ1bJFaFbGOz3UV3DDFmGYANr+SF+eapmiK5zV4=
github.com/hashicorp/raft v1.0.1-0.20190409200437-d9fe23f7d472/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI=
github.com/hashicorp/raft v1.1.0 h1:qPMePEczgbkiQsqCsRfuHRqvDUO+zmAInDaD5ptXlq0=
github.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM=
github.com/hashicorp/raft-boltdb v0.0.0-20150201200839-d1e82c1ec3f1 h1:LHTrLUnNkk+2YkO5EMG49q0lHdR9AZhDbCpu0+M3e0E=
@ -260,8 +243,6 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v0.0.0-20180523175426-90697d60dd84 h1:it29sI2IM490luSc3RAhp5WuCYnc6RtbfLVAB7nmC5M=
github.com/lib/pq v0.0.0-20180523175426-90697d60dd84/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lyft/protoc-gen-validate v0.0.0-20180911180927-64fcb82c878e h1:cgOn2iVzS/4UIrPj8PwNb9yW5/o6GVf0wV1ScGOcQKQ=
github.com/lyft/protoc-gen-validate v0.0.0-20180911180927-64fcb82c878e/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
@ -327,20 +308,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.0.0-20180328130430-f504d69affe1 h1:jtnwVoXwppTtQ4ApMgCb+G5CcW8OUvLlprWpB+x3e+8=
github.com/prometheus/client_golang v0.0.0-20180328130430-f504d69affe1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5 h1:cLL6NowurKLMfCeQy4tIeph12XNQWgANCNvdyrOYKV4=
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20180326160409-38c53a9f4bfc h1:tyg3EcZAmwCUe90Jzl4Qw6Af+ajuW8S9b1VFitMNOQs=
github.com/prometheus/common v0.0.0-20180326160409-38c53a9f4bfc/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d h1:RCcsxyRr6+/pLg6wr0cUjPovhEhSNOtPh0SOz6u3hGU=
github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 h1:Wdi9nwnhFNAlseAOekn6B5G/+GMtks9UKbvRU/CMM/o=
@ -385,7 +358,6 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -393,8 +365,6 @@ golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519 h1:x6rhz8Y9CjbgQkccRGmELH6K+
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190403144856-b630fd6fe46b h1:/zjbcJPEGAyu6Is/VBOALsgdi4z9+kz/Vtdm6S+beD0=
golang.org/x/net v0.0.0-20190403144856-b630fd6fe46b/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20170807180024-9a379c6b3e95/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -403,8 +373,6 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -413,8 +381,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5 h1:x6r4Jo0KNzOOzYd8lbcRsqjuqEASK6ob3auvWYM4/8U=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190508220229-2d0786266e9c h1:hDn6jm7snBX2O7+EeTk6Q4WXJfKt7MWgtiCCRi1rBoY=
golang.org/x/sys v0.0.0-20190508220229-2d0786266e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
@ -424,7 +390,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 h1:+DCIGbF/swA92ohVg0//6X2IVY3KZs6p9mix0ziNYJM=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
google.golang.org/api v0.0.0-20180829000535-087779f1d2c9 h1:z1TeLUmxf9ws9KLICfmX+KGXTs+rjm+aGWzfsv7MZ9w=
@ -433,8 +398,6 @@ google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRS
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v0.0.0-20180920234847-8997b5fa0873 h1:lD5DGIVfj/bkquhOM/bnbqvmwMFMmQblC3Ujbs8STUY=
google.golang.org/grpc v0.0.0-20180920234847-8997b5fa0873/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
@ -461,7 +424,6 @@ gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
istio.io/gogo-genproto v0.0.0-20190124151557-6d926a6e6feb/go.mod h1:eIDJ6jNk/IeJz6ODSksHl5Aiczy5JUq6vFhJWI5OtiI=
k8s.io/api v0.0.0-20180806132203-61b11ee65332/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=

View File

@ -57,6 +57,8 @@ const (
MatchNotIn
MatchIsEmpty
MatchIsNotEmpty
MatchMatches
MatchNotMatches
)
func (op MatchOperator) String() string {
@ -73,6 +75,10 @@ func (op MatchOperator) String() string {
return "Is Empty"
case MatchIsNotEmpty:
return "Is Not Empty"
case MatchMatches:
return "Matches"
case MatchNotMatches:
return "Not Matches"
default:
return "UNKNOWN"
}

View File

@ -3,9 +3,12 @@ package bexpr
import (
"fmt"
"reflect"
"regexp"
"strings"
)
var byteSliceTyp reflect.Type = reflect.TypeOf([]byte{})
var primitiveEqualityFns = map[reflect.Kind]func(first interface{}, second reflect.Value) bool{
reflect.Bool: doEqualBool,
reflect.Int: doEqualInt,
@ -87,6 +90,16 @@ func derefType(rtype reflect.Type) reflect.Type {
return rtype
}
func doMatchMatches(expression *MatchExpression, value reflect.Value) (bool, error) {
if !value.Type().ConvertibleTo(byteSliceTyp) {
return false, fmt.Errorf("Value of type %s is not convertible to []byte", value.Type())
}
re := expression.Value.Converted.(*regexp.Regexp)
return re.Match(value.Convert(byteSliceTyp).Interface().([]byte)), nil
}
func doMatchEqual(expression *MatchExpression, value reflect.Value) (bool, error) {
// NOTE: see preconditions in evaluateMatchExpressionRecurse
eqFn := primitiveEqualityFns[value.Kind()]
@ -186,6 +199,14 @@ func evaluateMatchExpressionRecurse(expression *MatchExpression, depth int, rval
return !result, nil
}
return false, err
case MatchMatches:
return doMatchMatches(expression, rvalue)
case MatchNotMatches:
result, err := doMatchMatches(expression, rvalue)
if err == nil {
return !result, nil
}
return false, err
default:
return false, fmt.Errorf("Invalid match operation: %d", expression.Operator)
}

View File

@ -15,6 +15,22 @@ type FieldName string
// Used to represent an arbitrary field name
const FieldNameAny FieldName = ""
type FieldPath []FieldName
func (path FieldPath) String() string {
var parts []string
for _, part := range path {
if part == FieldNameAny {
parts = append(parts, "<any>")
} else {
parts = append(parts, string(part))
}
}
return strings.Join(parts, ".")
}
// The FieldConfiguration struct represents how boolean expression
// validation and preparation should work for the given field. A field
// in this case is a single element of a selector.
@ -71,9 +87,15 @@ func generateFieldConfigurationInternal(rtype reflect.Type) (*FieldConfiguration
// Handle primitive types
if coerceFn, ok := primitiveCoercionFns[rtype.Kind()]; ok {
ops := []MatchOperator{MatchEqual, MatchNotEqual}
if rtype.Kind() == reflect.String {
ops = append(ops, MatchIn, MatchNotIn, MatchMatches, MatchNotMatches)
}
return &FieldConfiguration{
CoerceFn: coerceFn,
SupportedOperations: []MatchOperator{MatchEqual, MatchNotEqual},
SupportedOperations: ops,
}, nil
}
@ -306,3 +328,25 @@ func (configs FieldConfigurations) String() string {
configs.stringInternal(&builder, 0, "")
return builder.String()
}
type FieldConfigurationWalkFn func(path FieldPath, config *FieldConfiguration) bool
func (configs FieldConfigurations) walk(path FieldPath, walkFn FieldConfigurationWalkFn) bool {
for fieldName, fieldConfig := range configs {
newPath := append(path, fieldName)
if !walkFn(newPath, fieldConfig) {
return false
}
if !fieldConfig.SubFields.walk(newPath, walkFn) {
return false
}
}
return true
}
func (configs FieldConfigurations) Walk(walkFn FieldConfigurationWalkFn) bool {
return configs.walk(nil, walkFn)
}

File diff suppressed because it is too large Load Diff

View File

@ -58,7 +58,7 @@ ParenthesizedExpression "grouping" <- "(" _? expr:OrExpression _? ")" {
MatchExpression "match" <- MatchSelectorOpValue / MatchSelectorOp / MatchValueOpSelector
MatchSelectorOpValue "match" <- selector:Selector operator:(MatchEqual / MatchNotEqual / MatchContains / MatchNotContains) value:Value {
MatchSelectorOpValue "match" <- selector:Selector operator:(MatchEqual / MatchNotEqual / MatchContains / MatchNotContains / MatchMatches / MatchNotMatches) value:Value {
return &MatchExpression{Selector: selector.(Selector), Operator: operator.(MatchOperator), Value: value.(*MatchValue)}, nil
}
@ -96,7 +96,12 @@ MatchContains <- _ "contains" _ {
MatchNotContains <- _ "not" _ "contains" _ {
return MatchNotIn, nil
}
MatchMatches <- _ "matches" _ {
return MatchMatches, nil
}
MatchNotMatches <- _ "not" _ "matches" _ {
return MatchNotMatches, nil
}
Selector "selector" <- first:Identifier rest:SelectorOrIndex* {
sel := Selector{

View File

@ -2,6 +2,7 @@ package bexpr
import (
"fmt"
"regexp"
)
func validateRecurse(ast Expression, fields FieldConfigurations, maxRawValueLength int) (int, error) {
@ -96,6 +97,24 @@ func validateRecurse(ast Expression, fields FieldConfigurations, maxRawValueLeng
node.Value.Converted = coerced
}
if node.Operator == MatchMatches || node.Operator == MatchNotMatches {
var regRaw string
if strVal, ok := node.Value.Converted.(string); ok {
regRaw = strVal
} else if node.Value.Converted == nil {
regRaw = node.Value.Raw
} else {
return 1, fmt.Errorf("Match operator %q cannot be used with fields whose coercion functions return non string values", node.Operator)
}
re, err := regexp.Compile(regRaw)
if err != nil {
return 1, fmt.Errorf("Failed to compile regular expression %q: %v", regRaw, err)
}
node.Value.Converted = re
}
} else {
switch node.Operator {
case MatchIsEmpty, MatchIsNotEmpty:

2
vendor/modules.txt vendored
View File

@ -194,7 +194,7 @@ github.com/gregjones/httpcache/diskcache
github.com/hailocab/go-hostpool
# github.com/hashicorp/errwrap v1.0.0
github.com/hashicorp/errwrap
# github.com/hashicorp/go-bexpr v0.1.0
# github.com/hashicorp/go-bexpr v0.1.2
github.com/hashicorp/go-bexpr
# github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de
github.com/hashicorp/go-checkpoint

View File

@ -74,16 +74,16 @@ the following selectors and filter operations being supported:
| Selector | Supported Operations |
| ------------- | ---------------------------------- |
| `CheckID` | Equal, Not Equal |
| `Name` | Equal, Not Equal |
| `Node` | Equal, Not Equal |
| `Notes` | Equal, Not Equal |
| `Output` | Equal, Not Equal |
| `ServiceID` | Equal, Not Equal |
| `ServiceName` | Equal, Not Equal |
| ------------- | ------------------------------------------------- |
| `CheckID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Name` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Notes` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Output` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceTags` | In, Not In, Is Empty, Is Not Empty |
| `Status` | Equal, Not Equal |
| `Status` | Equal, Not Equal, In, Not In, Matches, Not Matches |
## Register Check

View File

@ -88,29 +88,31 @@ The filter is executed against each value in the service mapping with the
following selectors and filter operations being supported:
| Selector | Supported Operations |
| -------------------------------------- | ---------------------------------- |
| `Address` | Equal, Not Equal |
| -------------------------------------- | ------------------------------------------------- |
| `Address` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Connect.Native` | Equal, Not Equal |
| `EnableTagOverride` | Equal, Not Equal |
| `ID` | Equal, Not Equal |
| `Kind` | Equal, Not Equal |
| `Meta` | In, Not In, Is Empty, Is Not Empty |
| `Meta.<any>` | Equal, Not Equal |
| `ID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Kind` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Meta` | Is Empty, Is Not Empty, In, Not In |
| `Meta.<any>` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Port` | Equal, Not Equal |
| `Proxy.DestinationServiceID` | Equal, Not Equal |
| `Proxy.DestinationServiceName` | Equal, Not Equal |
| `Proxy.LocalServiceAddress` | Equal, Not Equal |
| `Proxy.DestinationServiceID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.DestinationServiceName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.LocalServiceAddress` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.LocalServicePort` | Equal, Not Equal |
| `Proxy.MeshGateway.Mode` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams` | Is Empty, Is Not Empty |
| `Proxy.Upstreams.Datacenter` | Equal, Not Equal |
| `Proxy.Upstreams.DestinationName` | Equal, Not Equal |
| `Proxy.Upstreams.DestinationNamespace` | Equal, Not Equal |
| `Proxy.Upstreams.DestinationType` | Equal, Not Equal |
| `Proxy.Upstreams.LocalBindAddress` | Equal, Not Equal |
| `Proxy.Upstreams.Datacenter` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams.DestinationName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams.DestinationNamespace` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams.DestinationType` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams.LocalBindAddress` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams.LocalBindPort` | Equal, Not Equal |
| `Service` | Equal, Not Equal |
| `TaggedAddresses` | In, Not In, Is Empty, Is Not Empty |
| `TaggedAddresses.<any>.Address` | Equal, Not Equal |
| `Proxy.Upstreams.MeshGateway.Mode` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `TaggedAddresses` | Is Empty, Is Not Empty, In, Not In |
| `TaggedAddresses.<any>.Address` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `TaggedAddresses.<any>.Port` | Equal, Not Equal |
| `Tags` | In, Not In, Is Empty, Is Not Empty |
| `Weights.Passing` | Equal, Not Equal |

View File

@ -345,15 +345,15 @@ The filter will be executed against each Node in the result list with
the following selectors and filter operations being supported:
| Selector | Supported Operations |
| ----------------------- | ---------------------------------- |
| `Address` | Equal, Not Equal |
| `Datacenter` | Equal, Not Equal |
| `ID` | Equal, Not Equal |
| `Meta` | In, Not In, Is Empty, Is Not Empty |
| `Meta.<any>` | Equal, Not Equal |
| `Node` | Equal, Not Equal |
| `TaggedAddresses` | In, Not In, Is Empty, Is Not Empty |
| `TaggedAddresses.<any>` | Equal, Not Equal |
| ----------------------- | -------------------------------------------------- |
| `Address` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Datacenter` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Meta` | Is Empty, Is Not Empty, In, Not In |
| `Meta.<any>` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `TaggedAddresses` | Is Empty, Is Not Empty, In, Not In |
| `TaggedAddresses.<any>` | Equal, Not Equal, In, Not In, Matches, Not Matches |
## List Services
@ -572,41 +572,43 @@ Filtering is executed against each entry in the top level result list with the
following selectors and filter operations being supported:
| Selector | Supported Operations |
| --------------------------------------------- | ---------------------------------- |
| `Address` | Equal, Not Equal |
| `Datacenter` | Equal, Not Equal |
| `ID` | Equal, Not Equal |
| `Node` | Equal, Not Equal |
| `NodeMeta` | In, Not In, Is Empty, Is Not Empty |
| `NodeMeta.<any>` | Equal, Not Equal |
| `ServiceAddress` | Equal, Not Equal |
| --------------------------------------------- | ------------------------------------------------- |
| `Address` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Datacenter` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `NodeMeta.<any>` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `NodeMeta` | Is Empty, Is Not Empty, In, Not In |
| `ServiceAddress` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceConnect.Native` | Equal, Not Equal |
| `ServiceEnableTagOverride` | Equal, Not Equal |
| `ServiceID` | Equal, Not Equal |
| `ServiceKind` | Equal, Not Equal |
| `ServiceMeta` | In, Not In, Is Empty, Is Not Empty |
| `ServiceMeta.<any>` | Equal, Not Equal |
| `ServiceName` | Equal, Not Equal |
| `ServiceID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceKind` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceMeta.<any>` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceMeta` | Is Empty, Is Not Empty, In, Not In |
| `ServiceName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServicePort` | Equal, Not Equal |
| `ServiceProxy.DestinationServiceID` | Equal, Not Equal |
| `ServiceProxy.DestinationServiceName` | Equal, Not Equal |
| `ServiceProxy.LocalServiceAddress` | Equal, Not Equal |
| `ServiceProxy.DestinationServiceID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceProxy.DestinationServiceName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceProxy.LocalServiceAddress` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceProxy.LocalServicePort` | Equal, Not Equal |
| `ServiceProxy.Upstreams` | Is Empty, Is Not Empty |
| `ServiceProxy.Upstreams.Datacenter` | Equal, Not Equal |
| `ServiceProxy.Upstreams.DestinationName` | Equal, Not Equal |
| `ServiceProxy.Upstreams.DestinationNamespace` | Equal, Not Equal |
| `ServiceProxy.Upstreams.DestinationType` | Equal, Not Equal |
| `ServiceProxy.Upstreams.LocalBindAddress` | Equal, Not Equal |
| `ServiceProxy.MeshGateway.Mode` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceProxy.Upstreams.Datacenter` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceProxy.Upstreams.DestinationName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceProxy.Upstreams.DestinationNamespace` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceProxy.Upstreams.DestinationType` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceProxy.Upstreams.LocalBindAddress` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceProxy.Upstreams.LocalBindPort` | Equal, Not Equal |
| `ServiceTaggedAddresses` | In, Not In, Is Empty, Is Not Empty |
| `ServiceTaggedAddresses.<any>.Address` | Equal, Not Equal |
| `ServiceProxy.Upstreams.MeshGateway.Mode` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceProxy.Upstreams` | Is Empty, Is Not Empty |
| `ServiceTaggedAddresses.<any>.Address` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceTaggedAddresses.<any>.Port` | Equal, Not Equal |
| `ServiceTaggedAddresses` | Is Empty, Is Not Empty, In, Not In |
| `ServiceTags` | In, Not In, Is Empty, Is Not Empty |
| `ServiceWeights.Passing` | Equal, Not Equal |
| `ServiceWeights.Warning` | Equal, Not Equal |
| `TaggedAddresses` | In, Not In, Is Empty, Is Not Empty |
| `TaggedAddresses.<any>` | Equal, Not Equal |
| `TaggedAddresses.<any>` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `TaggedAddresses` | Is Empty, Is Not Empty, In, Not In |
## List Nodes for Connect-capable Service
@ -716,30 +718,33 @@ The filter will be executed against each value in the `Services` mapping within
top level Node object. The following selectors and filter operations are supported:
| Selector | Supported Operations |
| -------------------------------------- | ---------------------------------- |
| `Address` | Equal, Not Equal |
| -------------------------------------- | -------------------------------------------------- |
| `Address` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Connect.Native` | Equal, Not Equal |
| `EnableTagOverride` | Equal, Not Equal |
| `ID` | Equal, Not Equal |
| `Kind` | Equal, Not Equal |
| `Meta` | In, Not In, Is Empty, Is Not Empty |
| `Meta.<any>` | Equal, Not Equal |
| `ID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Kind` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Meta` | Is Empty, Is Not Empty, In, Not In |
| `Meta.<any>` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Port` | Equal, Not Equal |
| `Proxy.DestinationServiceID` | Equal, Not Equal |
| `Proxy.DestinationServiceName` | Equal, Not Equal |
| `Proxy.LocalServiceAddress` | Equal, Not Equal |
| `Proxy.DestinationServiceID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.DestinationServiceName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.LocalServiceAddress` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.LocalServicePort` | Equal, Not Equal |
| `Proxy.MeshGateway.Mode` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams` | Is Empty, Is Not Empty |
| `Proxy.Upstreams.Datacenter` | Equal, Not Equal |
| `Proxy.Upstreams.DestinationName` | Equal, Not Equal |
| `Proxy.Upstreams.DestinationNamespace` | Equal, Not Equal |
| `Proxy.Upstreams.DestinationType` | Equal, Not Equal |
| `Proxy.Upstreams.LocalBindAddress` | Equal, Not Equal |
| `Proxy.Upstreams.Datacenter` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams.DestinationName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams.DestinationNamespace` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams.DestinationType` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams.LocalBindAddress` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Proxy.Upstreams.LocalBindPort` | Equal, Not Equal |
| `Service` | Equal, Not Equal |
| `TaggedAddresses` | In, Not In, Is Empty, Is Not Empty |
| `TaggedAddresses.<any>.Address` | Equal, Not Equal |
| `Proxy.Upstreams.MeshGateway.Mode` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `TaggedAddresses` | Is Empty, Is Not Empty, In, Not In |
| `TaggedAddresses.<any>.Address` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `TaggedAddresses.<any>.Port` | Equal, Not Equal |
| `Tags` | In, Not In, Is Empty, Is Not Empty |
| `Weights.Passing` | Equal, Not Equal |
| `Weights.Warning` | Equal, Not Equal |

View File

@ -78,11 +78,15 @@ those endpoints.
<Selector> is empty
<Selector> is not empty
// Contains checks
// Contains checks or Substring Matching
<Value> in <Selector>
<Value> not in <Selector>
<Selector> contains <Value>
<Selector> not contains <Value>
// Regular Expression Matching
<Selector> matches <Value>
<Selector> not matches <Value>
```
### Selectors

View File

@ -89,16 +89,16 @@ The filter will be executed against each health check in the results list with
the following selectors and filter operations being supported:
| Selector | Supported Operations |
| ------------- | ---------------------------------- |
| `CheckID` | Equal, Not Equal |
| `Name` | Equal, Not Equal |
| `Node` | Equal, Not Equal |
| `Notes` | Equal, Not Equal |
| `Output` | Equal, Not Equal |
| `ServiceID` | Equal, Not Equal |
| `ServiceName` | Equal, Not Equal |
| ------------- | -------------------------------------------------- |
| `CheckID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Name` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Notes` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Output` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceTags` | In, Not In, Is Empty, Is Not Empty |
| `Status` | Equal, Not Equal |
| `Status` | Equal, Not Equal, In, Not In, Matches, Not Matches |
## List Checks for Service
@ -173,16 +173,16 @@ the following selectors and filter operations being supported:
| Selector | Supported Operations |
| ------------- | ---------------------------------- |
| `CheckID` | Equal, Not Equal |
| `Name` | Equal, Not Equal |
| `Node` | Equal, Not Equal |
| `Notes` | Equal, Not Equal |
| `Output` | Equal, Not Equal |
| `ServiceID` | Equal, Not Equal |
| `ServiceName` | Equal, Not Equal |
| ------------- | -------------------------------------------------- |
| `CheckID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Name` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Notes` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Output` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceTags` | In, Not In, Is Empty, Is Not Empty |
| `Status` | Equal, Not Equal |
| `Status` | Equal, Not Equal, In, Not In, Matches, Not Matches |
## List Nodes for Service
@ -318,47 +318,49 @@ The filter will be executed against each entry in the top level results list wit
following selectors and filter operations being supported:
| Selector | Supported Operations |
| ---------------------------------------------- | ---------------------------------- |
| ---------------------------------------------- | -------------------------------------------------- |
| `Checks` | Is Empty, Is Not Empty |
| `Checks.CheckID` | Equal, Not Equal |
| `Checks.Name` | Equal, Not Equal |
| `Checks.Node` | Equal, Not Equal |
| `Checks.Notes` | Equal, Not Equal |
| `Checks.Output` | Equal, Not Equal |
| `Checks.ServiceID` | Equal, Not Equal |
| `Checks.ServiceName` | Equal, Not Equal |
| `Checks.CheckID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Checks.Name` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Checks.Node` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Checks.Notes` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Checks.Output` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Checks.ServiceID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Checks.ServiceName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Checks.ServiceTags` | In, Not In, Is Empty, Is Not Empty |
| `Checks.Status` | Equal, Not Equal |
| `Node.Address` | Equal, Not Equal |
| `Node.Datacenter` | Equal, Not Equal |
| `Node.ID` | Equal, Not Equal |
| `Node.Meta` | In, Not In, Is Empty, Is Not Empty |
| `Node.Meta.<any>` | Equal, Not Equal |
| `Node.Node` | Equal, Not Equal |
| `Node.TaggedAddresses` | In, Not In, Is Empty, Is Not Empty |
| `Node.TaggedAddresses.<any>` | Equal, Not Equal |
| `Service.Address` | Equal, Not Equal |
| `Checks.Status` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node.Address` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node.Datacenter` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node.ID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node.Meta` | Is Empty, Is Not Empty, In, Not In |
| `Node.Meta.<any>` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node.Node` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node.TaggedAddresses` | Is Empty, Is Not Empty, In, Not In |
| `Node.TaggedAddresses.<any>` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Address` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Connect.Native` | Equal, Not Equal |
| `Service.EnableTagOverride` | Equal, Not Equal |
| `Service.ID` | Equal, Not Equal |
| `Service.Kind` | Equal, Not Equal |
| `Service.Meta` | In, Not In, Is Empty, Is Not Empty |
| `Service.Meta.<any>` | Equal, Not Equal |
| `Service.ID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Kind` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Meta` | Is Empty, Is Not Empty, In, Not In |
| `Service.Meta.<any>` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Port` | Equal, Not Equal |
| `Service.Proxy.DestinationServiceID` | Equal, Not Equal |
| `Service.Proxy.DestinationServiceName` | Equal, Not Equal |
| `Service.Proxy.LocalServiceAddress` | Equal, Not Equal |
| `Service.Proxy.DestinationServiceID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Proxy.DestinationServiceName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Proxy.LocalServiceAddress` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Proxy.LocalServicePort` | Equal, Not Equal |
| `Service.Proxy.MeshGateway.Mode` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Proxy.Upstreams` | Is Empty, Is Not Empty |
| `Service.Proxy.Upstreams.Datacenter` | Equal, Not Equal |
| `Service.Proxy.Upstreams.DestinationName` | Equal, Not Equal |
| `Service.Proxy.Upstreams.DestinationNamespace` | Equal, Not Equal |
| `Service.Proxy.Upstreams.DestinationType` | Equal, Not Equal |
| `Service.Proxy.Upstreams.LocalBindAddress` | Equal, Not Equal |
| `Service.Proxy.Upstreams.Datacenter` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Proxy.Upstreams.DestinationName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Proxy.Upstreams.DestinationNamespace` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Proxy.Upstreams.DestinationType` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Proxy.Upstreams.LocalBindAddress` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Proxy.Upstreams.LocalBindPort` | Equal, Not Equal |
| `Service.Service` | Equal, Not Equal |
| `Service.TaggedAddresses` | In, Not In, Is Empty, Is Not Empty |
| `Service.TaggedAddresses.<any>.Address` | Equal, Not Equal |
| `Service.Proxy.Upstreams.MeshGateway.Mode` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.Service` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.TaggedAddresses` | Is Empty, Is Not Empty, In, Not In |
| `Service.TaggedAddresses.<any>.Address` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Service.TaggedAddresses.<any>.Port` | Equal, Not Equal |
| `Service.Tags` | In, Not In, Is Empty, Is Not Empty |
| `Service.Weights.Passing` | Equal, Not Equal |
@ -463,13 +465,13 @@ the following selectors and filter operations being supported:
| Selector | Supported Operations |
| ------------- | ---------------------------------- |
| `CheckID` | Equal, Not Equal |
| `Name` | Equal, Not Equal |
| `Node` | Equal, Not Equal |
| `Notes` | Equal, Not Equal |
| `Output` | Equal, Not Equal |
| `ServiceID` | Equal, Not Equal |
| `ServiceName` | Equal, Not Equal |
| ------------- | -------------------------------------------------- |
| `CheckID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Name` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Node` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Notes` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `Output` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceID` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
| `ServiceTags` | In, Not In, Is Empty, Is Not Empty |
| `Status` | Equal, Not Equal |
| `Status` | Equal, Not Equal, In, Not In, Matches, Not Matches |