Index arbitrary labels (#317)
* Add more fields to index when sql-caching is on.
* Restore the gvkKey helper, add event fields.
The UI team wasn't sure whether the event fields should go in the empty-string group or in 'events.k8s.io',
so let's go with both until/unless specified otherwise.
* More fixes to the fields to index:
- Remove the erroneously added management.cattle.io.nodes fields
- Use the builtin Event class, not events.k8s.io (by looking at the dashboard client code)
* Start on the virtual-field work.
* Map `Event.type` to `Event._type` for indexing.
* Add a unit test for field replacement for Event.type
* Add label processing.
* Don't test for transformation of event objects in the common module.
* Parse metadata.label queries differently.
* Improve a variable name that turned out to not be temporary.
* No need to specifically cache certain labels, as all are now cached.
* Add a test to verify simple label (m.labels.foo=blah) queries work.
* 'addLabelFields' never returns an error.
* Delete superseded function.
* Was calling 'addLabelFields' one time too many.
* Start using k8s ParseToRequirements
* Pull in the k8s parser.
* Successfully test for quotation marks.
* Add quoted strings to the lexer.
* Move to a forked k8s label lexer to include non-label tests.
* Improve and test the way quoted strings in the query are detected.
* Reinstate the original Apache license in the derived code.
Following clause 4.3 of the Apache license:
"You must cause any modified files to carry prominent notices stating that You changed the files..."
* Ignore case for operators.
* Test IN multiple-target-values
* Test the not-in operator.
* Ignore case for operators.
SQL is case-insensitive on field names and values, so this just adds consistency.
* Added tests for parsing EXISTS and NOT-EXISTS queries.
* Parse less-than and greater-than ops
* Lasso's `CacheFor` now takes a `watchable` argument.
* Support 'gt' and 'lt' as synonyms for '<' and '>'.
I see both types of operators being bandied about -- it's easy to support the aliases.
* typo fix
* Have the filter parser allow exist tests only on labels.
Also reduce the case where there's no namespace function.
* Specify hard-wired fields to index alphabetically.
* Remove unused variable.
* Parser: 'metadata.labels[FIELD]' is valid
* Pull in new gvk fields from main (and keep in alpha order).
* Fixed a couple of drops done during the last rebase.
* Add a reminder to keep the entries in alpha order.
* Test TransformLabels
* Remove TransformLabels
* Remove unused/unneeded code.
* Describe diffs between our label-selector parser and upstream's.
* Use the merged lasso 46333 work.
* Drop unused field.
* Tighten up the code.
* Specify which commit the label selector parser is based on.
* Allow both single-quoted and double-quoted value matching, doc difference.
* More review-driven changes:
- Stricter processing of m.l.name keys:
Require ending close-bracket for a start-bracket
- Comment fix
- Moving sql processing from lasso to steve: some changes missed in rebase
* Drop support for double-quotes for string values.
For now on only single-quotes (or none where possible) are allowed.
* Renaming and dropping an init block.
* Quoted strings are dropped from the filter queries
In particular, label values have a specific syntax: they must
start and end with a letter, and their innards may contain
only alnums '.', '-' and '_'. So there's no need for quoting.
And that means now that `=` and `==` do exact matches,
and the `~` operator does a partial match.
`!=` and `!~` negate -- note that `!~` is a stricter operation than `!=`,
in that given a set of possible string values, `!=` will accept more
of them than `!~`. Maybe I shouldn't have gone here, but these operators
reminded me of learning about `nicht durfen` and `nicht sollen` in German,
or something like that.
* Move a constant definition to the module level.
* Remove commented-out code.
* Remove unused func and adjacent redundant comment.
2025-01-30 19:57:23 +00:00
|
|
|
/*
|
|
|
|
Copyright 2014 The Kubernetes Authors.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
This file is derived from
|
|
|
|
https://github.com/kubernetes/apimachinery/blob/master/pkg/labels/selector_test.go
|
|
|
|
*/
|
|
|
|
|
|
|
|
package queryparser
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
|
|
"github.com/rancher/steve/pkg/stores/sqlpartition/selection"
|
|
|
|
"k8s.io/apimachinery/pkg/util/sets"
|
|
|
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ignoreDetail = cmpopts.IgnoreFields(field.Error{}, "Detail")
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestSelectorParse(t *testing.T) {
|
|
|
|
testGoodStrings := []string{
|
|
|
|
"x=a,y=b,z=c",
|
|
|
|
"",
|
|
|
|
"x!=a,y=b",
|
|
|
|
"close ~ value",
|
|
|
|
"notclose !~ value",
|
|
|
|
"x>1",
|
|
|
|
"x>1,z<5",
|
|
|
|
"x gt 1,z lt 5",
|
|
|
|
`y == def`,
|
|
|
|
"metadata.labels.im-here",
|
|
|
|
"!metadata.labels.im-not-here",
|
|
|
|
"metadata.labels[im.here]",
|
|
|
|
"!metadata.labels[im.not.here]",
|
|
|
|
"metadata.labels[k8s.io/meta-stuff] ~ has-dashes_underscores.dots.only",
|
2025-05-13 18:40:54 +00:00
|
|
|
`metadata.labels[k8s.io/meta-stuff] ~ "m!a@t#c$h%e^v&e*r(y)t-_i=n+g)t{o[$]c}o]m|m\\a:;'<.>"`,
|
|
|
|
`x="double quotes ok"`,
|
|
|
|
`x='single quotes ok'`,
|
|
|
|
`x="double quotes with \\ and \" ok"`,
|
|
|
|
`x='single quotes with \\ and \' ok'`,
|
Index arbitrary labels (#317)
* Add more fields to index when sql-caching is on.
* Restore the gvkKey helper, add event fields.
The UI team wasn't sure whether the event fields should go in the empty-string group or in 'events.k8s.io',
so let's go with both until/unless specified otherwise.
* More fixes to the fields to index:
- Remove the erroneously added management.cattle.io.nodes fields
- Use the builtin Event class, not events.k8s.io (by looking at the dashboard client code)
* Start on the virtual-field work.
* Map `Event.type` to `Event._type` for indexing.
* Add a unit test for field replacement for Event.type
* Add label processing.
* Don't test for transformation of event objects in the common module.
* Parse metadata.label queries differently.
* Improve a variable name that turned out to not be temporary.
* No need to specifically cache certain labels, as all are now cached.
* Add a test to verify simple label (m.labels.foo=blah) queries work.
* 'addLabelFields' never returns an error.
* Delete superseded function.
* Was calling 'addLabelFields' one time too many.
* Start using k8s ParseToRequirements
* Pull in the k8s parser.
* Successfully test for quotation marks.
* Add quoted strings to the lexer.
* Move to a forked k8s label lexer to include non-label tests.
* Improve and test the way quoted strings in the query are detected.
* Reinstate the original Apache license in the derived code.
Following clause 4.3 of the Apache license:
"You must cause any modified files to carry prominent notices stating that You changed the files..."
* Ignore case for operators.
* Test IN multiple-target-values
* Test the not-in operator.
* Ignore case for operators.
SQL is case-insensitive on field names and values, so this just adds consistency.
* Added tests for parsing EXISTS and NOT-EXISTS queries.
* Parse less-than and greater-than ops
* Lasso's `CacheFor` now takes a `watchable` argument.
* Support 'gt' and 'lt' as synonyms for '<' and '>'.
I see both types of operators being bandied about -- it's easy to support the aliases.
* typo fix
* Have the filter parser allow exist tests only on labels.
Also reduce the case where there's no namespace function.
* Specify hard-wired fields to index alphabetically.
* Remove unused variable.
* Parser: 'metadata.labels[FIELD]' is valid
* Pull in new gvk fields from main (and keep in alpha order).
* Fixed a couple of drops done during the last rebase.
* Add a reminder to keep the entries in alpha order.
* Test TransformLabels
* Remove TransformLabels
* Remove unused/unneeded code.
* Describe diffs between our label-selector parser and upstream's.
* Use the merged lasso 46333 work.
* Drop unused field.
* Tighten up the code.
* Specify which commit the label selector parser is based on.
* Allow both single-quoted and double-quoted value matching, doc difference.
* More review-driven changes:
- Stricter processing of m.l.name keys:
Require ending close-bracket for a start-bracket
- Comment fix
- Moving sql processing from lasso to steve: some changes missed in rebase
* Drop support for double-quotes for string values.
For now on only single-quotes (or none where possible) are allowed.
* Renaming and dropping an init block.
* Quoted strings are dropped from the filter queries
In particular, label values have a specific syntax: they must
start and end with a letter, and their innards may contain
only alnums '.', '-' and '_'. So there's no need for quoting.
And that means now that `=` and `==` do exact matches,
and the `~` operator does a partial match.
`!=` and `!~` negate -- note that `!~` is a stricter operation than `!=`,
in that given a set of possible string values, `!=` will accept more
of them than `!~`. Maybe I shouldn't have gone here, but these operators
reminded me of learning about `nicht durfen` and `nicht sollen` in German,
or something like that.
* Move a constant definition to the module level.
* Remove commented-out code.
* Remove unused func and adjacent redundant comment.
2025-01-30 19:57:23 +00:00
|
|
|
}
|
|
|
|
testBadStrings := []string{
|
|
|
|
"!no-label-absence-test",
|
|
|
|
"no-label-presence-test",
|
|
|
|
"x=a||y=b",
|
|
|
|
"x==a==b",
|
|
|
|
"!x=a",
|
|
|
|
"x<a",
|
|
|
|
"x=",
|
|
|
|
"x= ",
|
|
|
|
"x=,z= ",
|
|
|
|
"x= ,z= ",
|
|
|
|
"x ~",
|
|
|
|
"x !~",
|
|
|
|
"~ val",
|
|
|
|
"!~ val",
|
|
|
|
"= val",
|
|
|
|
"== val",
|
|
|
|
"metadata.labels-im.here",
|
|
|
|
"metadata.labels[missing/close-bracket",
|
|
|
|
"!metadata.labels(im.not.here)",
|
|
|
|
}
|
|
|
|
for _, test := range testGoodStrings {
|
|
|
|
_, err := Parse(test)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("%v: error %v (%#v)\n", test, err, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, test := range testBadStrings {
|
|
|
|
_, err := Parse(test)
|
|
|
|
if err == nil {
|
|
|
|
t.Errorf("%v: did not get expected error\n", test)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLexer(t *testing.T) {
|
|
|
|
testcases := []struct {
|
|
|
|
s string
|
|
|
|
t Token
|
|
|
|
}{
|
|
|
|
{"", EndOfStringToken},
|
|
|
|
{",", CommaToken},
|
|
|
|
{"notin", NotInToken},
|
|
|
|
{"in", InToken},
|
|
|
|
{"=", EqualsToken},
|
|
|
|
{"==", DoubleEqualsToken},
|
|
|
|
{">", GreaterThanToken},
|
|
|
|
{"<", LessThanToken},
|
|
|
|
//Note that Lex returns the longest valid token found
|
|
|
|
{"!", DoesNotExistToken},
|
|
|
|
{"!=", NotEqualsToken},
|
|
|
|
{"(", OpenParToken},
|
|
|
|
{")", ClosedParToken},
|
2025-05-13 18:40:54 +00:00
|
|
|
{`'sq string'`, QuotedStringToken},
|
|
|
|
{`"dq string"`, QuotedStringToken},
|
Index arbitrary labels (#317)
* Add more fields to index when sql-caching is on.
* Restore the gvkKey helper, add event fields.
The UI team wasn't sure whether the event fields should go in the empty-string group or in 'events.k8s.io',
so let's go with both until/unless specified otherwise.
* More fixes to the fields to index:
- Remove the erroneously added management.cattle.io.nodes fields
- Use the builtin Event class, not events.k8s.io (by looking at the dashboard client code)
* Start on the virtual-field work.
* Map `Event.type` to `Event._type` for indexing.
* Add a unit test for field replacement for Event.type
* Add label processing.
* Don't test for transformation of event objects in the common module.
* Parse metadata.label queries differently.
* Improve a variable name that turned out to not be temporary.
* No need to specifically cache certain labels, as all are now cached.
* Add a test to verify simple label (m.labels.foo=blah) queries work.
* 'addLabelFields' never returns an error.
* Delete superseded function.
* Was calling 'addLabelFields' one time too many.
* Start using k8s ParseToRequirements
* Pull in the k8s parser.
* Successfully test for quotation marks.
* Add quoted strings to the lexer.
* Move to a forked k8s label lexer to include non-label tests.
* Improve and test the way quoted strings in the query are detected.
* Reinstate the original Apache license in the derived code.
Following clause 4.3 of the Apache license:
"You must cause any modified files to carry prominent notices stating that You changed the files..."
* Ignore case for operators.
* Test IN multiple-target-values
* Test the not-in operator.
* Ignore case for operators.
SQL is case-insensitive on field names and values, so this just adds consistency.
* Added tests for parsing EXISTS and NOT-EXISTS queries.
* Parse less-than and greater-than ops
* Lasso's `CacheFor` now takes a `watchable` argument.
* Support 'gt' and 'lt' as synonyms for '<' and '>'.
I see both types of operators being bandied about -- it's easy to support the aliases.
* typo fix
* Have the filter parser allow exist tests only on labels.
Also reduce the case where there's no namespace function.
* Specify hard-wired fields to index alphabetically.
* Remove unused variable.
* Parser: 'metadata.labels[FIELD]' is valid
* Pull in new gvk fields from main (and keep in alpha order).
* Fixed a couple of drops done during the last rebase.
* Add a reminder to keep the entries in alpha order.
* Test TransformLabels
* Remove TransformLabels
* Remove unused/unneeded code.
* Describe diffs between our label-selector parser and upstream's.
* Use the merged lasso 46333 work.
* Drop unused field.
* Tighten up the code.
* Specify which commit the label selector parser is based on.
* Allow both single-quoted and double-quoted value matching, doc difference.
* More review-driven changes:
- Stricter processing of m.l.name keys:
Require ending close-bracket for a start-bracket
- Comment fix
- Moving sql processing from lasso to steve: some changes missed in rebase
* Drop support for double-quotes for string values.
For now on only single-quotes (or none where possible) are allowed.
* Renaming and dropping an init block.
* Quoted strings are dropped from the filter queries
In particular, label values have a specific syntax: they must
start and end with a letter, and their innards may contain
only alnums '.', '-' and '_'. So there's no need for quoting.
And that means now that `=` and `==` do exact matches,
and the `~` operator does a partial match.
`!=` and `!~` negate -- note that `!~` is a stricter operation than `!=`,
in that given a set of possible string values, `!=` will accept more
of them than `!~`. Maybe I shouldn't have gone here, but these operators
reminded me of learning about `nicht durfen` and `nicht sollen` in German,
or something like that.
* Move a constant definition to the module level.
* Remove commented-out code.
* Remove unused func and adjacent redundant comment.
2025-01-30 19:57:23 +00:00
|
|
|
{"~", PartialEqualsToken},
|
|
|
|
{"!~", NotPartialEqualsToken},
|
|
|
|
{"||", ErrorToken},
|
2025-05-13 18:40:54 +00:00
|
|
|
{`"double-quoted string"`, QuotedStringToken},
|
|
|
|
{`'single-quoted string'`, QuotedStringToken},
|
Index arbitrary labels (#317)
* Add more fields to index when sql-caching is on.
* Restore the gvkKey helper, add event fields.
The UI team wasn't sure whether the event fields should go in the empty-string group or in 'events.k8s.io',
so let's go with both until/unless specified otherwise.
* More fixes to the fields to index:
- Remove the erroneously added management.cattle.io.nodes fields
- Use the builtin Event class, not events.k8s.io (by looking at the dashboard client code)
* Start on the virtual-field work.
* Map `Event.type` to `Event._type` for indexing.
* Add a unit test for field replacement for Event.type
* Add label processing.
* Don't test for transformation of event objects in the common module.
* Parse metadata.label queries differently.
* Improve a variable name that turned out to not be temporary.
* No need to specifically cache certain labels, as all are now cached.
* Add a test to verify simple label (m.labels.foo=blah) queries work.
* 'addLabelFields' never returns an error.
* Delete superseded function.
* Was calling 'addLabelFields' one time too many.
* Start using k8s ParseToRequirements
* Pull in the k8s parser.
* Successfully test for quotation marks.
* Add quoted strings to the lexer.
* Move to a forked k8s label lexer to include non-label tests.
* Improve and test the way quoted strings in the query are detected.
* Reinstate the original Apache license in the derived code.
Following clause 4.3 of the Apache license:
"You must cause any modified files to carry prominent notices stating that You changed the files..."
* Ignore case for operators.
* Test IN multiple-target-values
* Test the not-in operator.
* Ignore case for operators.
SQL is case-insensitive on field names and values, so this just adds consistency.
* Added tests for parsing EXISTS and NOT-EXISTS queries.
* Parse less-than and greater-than ops
* Lasso's `CacheFor` now takes a `watchable` argument.
* Support 'gt' and 'lt' as synonyms for '<' and '>'.
I see both types of operators being bandied about -- it's easy to support the aliases.
* typo fix
* Have the filter parser allow exist tests only on labels.
Also reduce the case where there's no namespace function.
* Specify hard-wired fields to index alphabetically.
* Remove unused variable.
* Parser: 'metadata.labels[FIELD]' is valid
* Pull in new gvk fields from main (and keep in alpha order).
* Fixed a couple of drops done during the last rebase.
* Add a reminder to keep the entries in alpha order.
* Test TransformLabels
* Remove TransformLabels
* Remove unused/unneeded code.
* Describe diffs between our label-selector parser and upstream's.
* Use the merged lasso 46333 work.
* Drop unused field.
* Tighten up the code.
* Specify which commit the label selector parser is based on.
* Allow both single-quoted and double-quoted value matching, doc difference.
* More review-driven changes:
- Stricter processing of m.l.name keys:
Require ending close-bracket for a start-bracket
- Comment fix
- Moving sql processing from lasso to steve: some changes missed in rebase
* Drop support for double-quotes for string values.
For now on only single-quotes (or none where possible) are allowed.
* Renaming and dropping an init block.
* Quoted strings are dropped from the filter queries
In particular, label values have a specific syntax: they must
start and end with a letter, and their innards may contain
only alnums '.', '-' and '_'. So there's no need for quoting.
And that means now that `=` and `==` do exact matches,
and the `~` operator does a partial match.
`!=` and `!~` negate -- note that `!~` is a stricter operation than `!=`,
in that given a set of possible string values, `!=` will accept more
of them than `!~`. Maybe I shouldn't have gone here, but these operators
reminded me of learning about `nicht durfen` and `nicht sollen` in German,
or something like that.
* Move a constant definition to the module level.
* Remove commented-out code.
* Remove unused func and adjacent redundant comment.
2025-01-30 19:57:23 +00:00
|
|
|
}
|
|
|
|
for _, v := range testcases {
|
|
|
|
l := &Lexer{s: v.s, pos: 0}
|
|
|
|
token, lit := l.Lex()
|
|
|
|
if token != v.t {
|
|
|
|
t.Errorf("Got %d it should be %d for '%s'", token, v.t, v.s)
|
|
|
|
}
|
2025-05-13 18:40:54 +00:00
|
|
|
if v.t != ErrorToken {
|
|
|
|
exp := v.s
|
|
|
|
if v.t == QuotedStringToken {
|
|
|
|
exp = exp[1 : len(exp)-1]
|
|
|
|
}
|
|
|
|
if lit != exp {
|
|
|
|
t.Errorf("Got '%s' it should be '%s'", lit, exp)
|
|
|
|
}
|
Index arbitrary labels (#317)
* Add more fields to index when sql-caching is on.
* Restore the gvkKey helper, add event fields.
The UI team wasn't sure whether the event fields should go in the empty-string group or in 'events.k8s.io',
so let's go with both until/unless specified otherwise.
* More fixes to the fields to index:
- Remove the erroneously added management.cattle.io.nodes fields
- Use the builtin Event class, not events.k8s.io (by looking at the dashboard client code)
* Start on the virtual-field work.
* Map `Event.type` to `Event._type` for indexing.
* Add a unit test for field replacement for Event.type
* Add label processing.
* Don't test for transformation of event objects in the common module.
* Parse metadata.label queries differently.
* Improve a variable name that turned out to not be temporary.
* No need to specifically cache certain labels, as all are now cached.
* Add a test to verify simple label (m.labels.foo=blah) queries work.
* 'addLabelFields' never returns an error.
* Delete superseded function.
* Was calling 'addLabelFields' one time too many.
* Start using k8s ParseToRequirements
* Pull in the k8s parser.
* Successfully test for quotation marks.
* Add quoted strings to the lexer.
* Move to a forked k8s label lexer to include non-label tests.
* Improve and test the way quoted strings in the query are detected.
* Reinstate the original Apache license in the derived code.
Following clause 4.3 of the Apache license:
"You must cause any modified files to carry prominent notices stating that You changed the files..."
* Ignore case for operators.
* Test IN multiple-target-values
* Test the not-in operator.
* Ignore case for operators.
SQL is case-insensitive on field names and values, so this just adds consistency.
* Added tests for parsing EXISTS and NOT-EXISTS queries.
* Parse less-than and greater-than ops
* Lasso's `CacheFor` now takes a `watchable` argument.
* Support 'gt' and 'lt' as synonyms for '<' and '>'.
I see both types of operators being bandied about -- it's easy to support the aliases.
* typo fix
* Have the filter parser allow exist tests only on labels.
Also reduce the case where there's no namespace function.
* Specify hard-wired fields to index alphabetically.
* Remove unused variable.
* Parser: 'metadata.labels[FIELD]' is valid
* Pull in new gvk fields from main (and keep in alpha order).
* Fixed a couple of drops done during the last rebase.
* Add a reminder to keep the entries in alpha order.
* Test TransformLabels
* Remove TransformLabels
* Remove unused/unneeded code.
* Describe diffs between our label-selector parser and upstream's.
* Use the merged lasso 46333 work.
* Drop unused field.
* Tighten up the code.
* Specify which commit the label selector parser is based on.
* Allow both single-quoted and double-quoted value matching, doc difference.
* More review-driven changes:
- Stricter processing of m.l.name keys:
Require ending close-bracket for a start-bracket
- Comment fix
- Moving sql processing from lasso to steve: some changes missed in rebase
* Drop support for double-quotes for string values.
For now on only single-quotes (or none where possible) are allowed.
* Renaming and dropping an init block.
* Quoted strings are dropped from the filter queries
In particular, label values have a specific syntax: they must
start and end with a letter, and their innards may contain
only alnums '.', '-' and '_'. So there's no need for quoting.
And that means now that `=` and `==` do exact matches,
and the `~` operator does a partial match.
`!=` and `!~` negate -- note that `!~` is a stricter operation than `!=`,
in that given a set of possible string values, `!=` will accept more
of them than `!~`. Maybe I shouldn't have gone here, but these operators
reminded me of learning about `nicht durfen` and `nicht sollen` in German,
or something like that.
* Move a constant definition to the module level.
* Remove commented-out code.
* Remove unused func and adjacent redundant comment.
2025-01-30 19:57:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func min(l, r int) (m int) {
|
|
|
|
m = r
|
|
|
|
if l < r {
|
|
|
|
m = l
|
|
|
|
}
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLexerSequence(t *testing.T) {
|
|
|
|
testcases := []struct {
|
|
|
|
s string
|
|
|
|
t []Token
|
|
|
|
}{
|
|
|
|
{"key in ( value )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, ClosedParToken}},
|
|
|
|
{"key notin ( value )", []Token{IdentifierToken, NotInToken, OpenParToken, IdentifierToken, ClosedParToken}},
|
|
|
|
{"key in ( value1, value2 )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, CommaToken, IdentifierToken, ClosedParToken}},
|
|
|
|
{"key", []Token{IdentifierToken}},
|
|
|
|
{"!key", []Token{DoesNotExistToken, IdentifierToken}},
|
|
|
|
{"()", []Token{OpenParToken, ClosedParToken}},
|
|
|
|
{"x in (),y", []Token{IdentifierToken, InToken, OpenParToken, ClosedParToken, CommaToken, IdentifierToken}},
|
|
|
|
{"== != (), = notin", []Token{DoubleEqualsToken, NotEqualsToken, OpenParToken, ClosedParToken, CommaToken, EqualsToken, NotInToken}},
|
|
|
|
{"key>2", []Token{IdentifierToken, GreaterThanToken, IdentifierToken}},
|
|
|
|
{"key<1", []Token{IdentifierToken, LessThanToken, IdentifierToken}},
|
|
|
|
{"key gt 3", []Token{IdentifierToken, IdentifierToken, IdentifierToken}},
|
|
|
|
{"key lt 4", []Token{IdentifierToken, IdentifierToken, IdentifierToken}},
|
2025-05-13 18:40:54 +00:00
|
|
|
{`key = 'sqs'`, []Token{IdentifierToken, EqualsToken, QuotedStringToken}},
|
|
|
|
{`key = "dqs"`, []Token{IdentifierToken, EqualsToken, QuotedStringToken}},
|
Index arbitrary labels (#317)
* Add more fields to index when sql-caching is on.
* Restore the gvkKey helper, add event fields.
The UI team wasn't sure whether the event fields should go in the empty-string group or in 'events.k8s.io',
so let's go with both until/unless specified otherwise.
* More fixes to the fields to index:
- Remove the erroneously added management.cattle.io.nodes fields
- Use the builtin Event class, not events.k8s.io (by looking at the dashboard client code)
* Start on the virtual-field work.
* Map `Event.type` to `Event._type` for indexing.
* Add a unit test for field replacement for Event.type
* Add label processing.
* Don't test for transformation of event objects in the common module.
* Parse metadata.label queries differently.
* Improve a variable name that turned out to not be temporary.
* No need to specifically cache certain labels, as all are now cached.
* Add a test to verify simple label (m.labels.foo=blah) queries work.
* 'addLabelFields' never returns an error.
* Delete superseded function.
* Was calling 'addLabelFields' one time too many.
* Start using k8s ParseToRequirements
* Pull in the k8s parser.
* Successfully test for quotation marks.
* Add quoted strings to the lexer.
* Move to a forked k8s label lexer to include non-label tests.
* Improve and test the way quoted strings in the query are detected.
* Reinstate the original Apache license in the derived code.
Following clause 4.3 of the Apache license:
"You must cause any modified files to carry prominent notices stating that You changed the files..."
* Ignore case for operators.
* Test IN multiple-target-values
* Test the not-in operator.
* Ignore case for operators.
SQL is case-insensitive on field names and values, so this just adds consistency.
* Added tests for parsing EXISTS and NOT-EXISTS queries.
* Parse less-than and greater-than ops
* Lasso's `CacheFor` now takes a `watchable` argument.
* Support 'gt' and 'lt' as synonyms for '<' and '>'.
I see both types of operators being bandied about -- it's easy to support the aliases.
* typo fix
* Have the filter parser allow exist tests only on labels.
Also reduce the case where there's no namespace function.
* Specify hard-wired fields to index alphabetically.
* Remove unused variable.
* Parser: 'metadata.labels[FIELD]' is valid
* Pull in new gvk fields from main (and keep in alpha order).
* Fixed a couple of drops done during the last rebase.
* Add a reminder to keep the entries in alpha order.
* Test TransformLabels
* Remove TransformLabels
* Remove unused/unneeded code.
* Describe diffs between our label-selector parser and upstream's.
* Use the merged lasso 46333 work.
* Drop unused field.
* Tighten up the code.
* Specify which commit the label selector parser is based on.
* Allow both single-quoted and double-quoted value matching, doc difference.
* More review-driven changes:
- Stricter processing of m.l.name keys:
Require ending close-bracket for a start-bracket
- Comment fix
- Moving sql processing from lasso to steve: some changes missed in rebase
* Drop support for double-quotes for string values.
For now on only single-quotes (or none where possible) are allowed.
* Renaming and dropping an init block.
* Quoted strings are dropped from the filter queries
In particular, label values have a specific syntax: they must
start and end with a letter, and their innards may contain
only alnums '.', '-' and '_'. So there's no need for quoting.
And that means now that `=` and `==` do exact matches,
and the `~` operator does a partial match.
`!=` and `!~` negate -- note that `!~` is a stricter operation than `!=`,
in that given a set of possible string values, `!=` will accept more
of them than `!~`. Maybe I shouldn't have gone here, but these operators
reminded me of learning about `nicht durfen` and `nicht sollen` in German,
or something like that.
* Move a constant definition to the module level.
* Remove commented-out code.
* Remove unused func and adjacent redundant comment.
2025-01-30 19:57:23 +00:00
|
|
|
{"key=value", []Token{IdentifierToken, EqualsToken, IdentifierToken}},
|
|
|
|
{"key == value", []Token{IdentifierToken, DoubleEqualsToken, IdentifierToken}},
|
|
|
|
{"key ~ value", []Token{IdentifierToken, PartialEqualsToken, IdentifierToken}},
|
|
|
|
{"key~ value", []Token{IdentifierToken, PartialEqualsToken, IdentifierToken}},
|
|
|
|
{"key ~value", []Token{IdentifierToken, PartialEqualsToken, IdentifierToken}},
|
|
|
|
{"key~value", []Token{IdentifierToken, PartialEqualsToken, IdentifierToken}},
|
|
|
|
{"key !~ value", []Token{IdentifierToken, NotPartialEqualsToken, IdentifierToken}},
|
|
|
|
{"key!~ value", []Token{IdentifierToken, NotPartialEqualsToken, IdentifierToken}},
|
|
|
|
{"key !~value", []Token{IdentifierToken, NotPartialEqualsToken, IdentifierToken}},
|
|
|
|
{"key!~value", []Token{IdentifierToken, NotPartialEqualsToken, IdentifierToken}},
|
|
|
|
}
|
|
|
|
for _, v := range testcases {
|
|
|
|
var tokens []Token
|
|
|
|
l := &Lexer{s: v.s, pos: 0}
|
|
|
|
for {
|
|
|
|
token, _ := l.Lex()
|
|
|
|
if token == EndOfStringToken {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
tokens = append(tokens, token)
|
|
|
|
}
|
|
|
|
if len(tokens) != len(v.t) {
|
|
|
|
t.Errorf("Bad number of tokens for '%s': got %d, wanted %d (got %v)", v.s, len(tokens), len(v.t), tokens)
|
|
|
|
}
|
|
|
|
for i := 0; i < min(len(tokens), len(v.t)); i++ {
|
|
|
|
if tokens[i] != v.t[i] {
|
|
|
|
t.Errorf("Test '%s': Mismatching in token type found '%v' it should be '%v'", v.s, tokens[i], v.t[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-05-13 18:40:54 +00:00
|
|
|
|
Index arbitrary labels (#317)
* Add more fields to index when sql-caching is on.
* Restore the gvkKey helper, add event fields.
The UI team wasn't sure whether the event fields should go in the empty-string group or in 'events.k8s.io',
so let's go with both until/unless specified otherwise.
* More fixes to the fields to index:
- Remove the erroneously added management.cattle.io.nodes fields
- Use the builtin Event class, not events.k8s.io (by looking at the dashboard client code)
* Start on the virtual-field work.
* Map `Event.type` to `Event._type` for indexing.
* Add a unit test for field replacement for Event.type
* Add label processing.
* Don't test for transformation of event objects in the common module.
* Parse metadata.label queries differently.
* Improve a variable name that turned out to not be temporary.
* No need to specifically cache certain labels, as all are now cached.
* Add a test to verify simple label (m.labels.foo=blah) queries work.
* 'addLabelFields' never returns an error.
* Delete superseded function.
* Was calling 'addLabelFields' one time too many.
* Start using k8s ParseToRequirements
* Pull in the k8s parser.
* Successfully test for quotation marks.
* Add quoted strings to the lexer.
* Move to a forked k8s label lexer to include non-label tests.
* Improve and test the way quoted strings in the query are detected.
* Reinstate the original Apache license in the derived code.
Following clause 4.3 of the Apache license:
"You must cause any modified files to carry prominent notices stating that You changed the files..."
* Ignore case for operators.
* Test IN multiple-target-values
* Test the not-in operator.
* Ignore case for operators.
SQL is case-insensitive on field names and values, so this just adds consistency.
* Added tests for parsing EXISTS and NOT-EXISTS queries.
* Parse less-than and greater-than ops
* Lasso's `CacheFor` now takes a `watchable` argument.
* Support 'gt' and 'lt' as synonyms for '<' and '>'.
I see both types of operators being bandied about -- it's easy to support the aliases.
* typo fix
* Have the filter parser allow exist tests only on labels.
Also reduce the case where there's no namespace function.
* Specify hard-wired fields to index alphabetically.
* Remove unused variable.
* Parser: 'metadata.labels[FIELD]' is valid
* Pull in new gvk fields from main (and keep in alpha order).
* Fixed a couple of drops done during the last rebase.
* Add a reminder to keep the entries in alpha order.
* Test TransformLabels
* Remove TransformLabels
* Remove unused/unneeded code.
* Describe diffs between our label-selector parser and upstream's.
* Use the merged lasso 46333 work.
* Drop unused field.
* Tighten up the code.
* Specify which commit the label selector parser is based on.
* Allow both single-quoted and double-quoted value matching, doc difference.
* More review-driven changes:
- Stricter processing of m.l.name keys:
Require ending close-bracket for a start-bracket
- Comment fix
- Moving sql processing from lasso to steve: some changes missed in rebase
* Drop support for double-quotes for string values.
For now on only single-quotes (or none where possible) are allowed.
* Renaming and dropping an init block.
* Quoted strings are dropped from the filter queries
In particular, label values have a specific syntax: they must
start and end with a letter, and their innards may contain
only alnums '.', '-' and '_'. So there's no need for quoting.
And that means now that `=` and `==` do exact matches,
and the `~` operator does a partial match.
`!=` and `!~` negate -- note that `!~` is a stricter operation than `!=`,
in that given a set of possible string values, `!=` will accept more
of them than `!~`. Maybe I shouldn't have gone here, but these operators
reminded me of learning about `nicht durfen` and `nicht sollen` in German,
or something like that.
* Move a constant definition to the module level.
* Remove commented-out code.
* Remove unused func and adjacent redundant comment.
2025-01-30 19:57:23 +00:00
|
|
|
func TestParserLookahead(t *testing.T) {
|
|
|
|
testcases := []struct {
|
|
|
|
s string
|
|
|
|
t []Token
|
|
|
|
}{
|
|
|
|
{"key in ( value )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
|
|
|
|
{"key notin ( value )", []Token{IdentifierToken, NotInToken, OpenParToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
|
|
|
|
{"key in ( value1, value2 )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, CommaToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
|
|
|
|
{"key", []Token{IdentifierToken, EndOfStringToken}},
|
|
|
|
{"!key", []Token{DoesNotExistToken, IdentifierToken, EndOfStringToken}},
|
|
|
|
{"()", []Token{OpenParToken, ClosedParToken, EndOfStringToken}},
|
|
|
|
{"", []Token{EndOfStringToken}},
|
|
|
|
{"x in (),y", []Token{IdentifierToken, InToken, OpenParToken, ClosedParToken, CommaToken, IdentifierToken, EndOfStringToken}},
|
|
|
|
{"== != (), = notin", []Token{DoubleEqualsToken, NotEqualsToken, OpenParToken, ClosedParToken, CommaToken, EqualsToken, NotInToken, EndOfStringToken}},
|
|
|
|
{"key>2", []Token{IdentifierToken, GreaterThanToken, IdentifierToken, EndOfStringToken}},
|
|
|
|
{"key<1", []Token{IdentifierToken, LessThanToken, IdentifierToken, EndOfStringToken}},
|
2025-05-13 18:40:54 +00:00
|
|
|
{"key gt 3", []Token{IdentifierToken, IdentifierToken, IdentifierToken, EndOfStringToken}},
|
|
|
|
{"key lt 4", []Token{IdentifierToken, IdentifierToken, IdentifierToken, EndOfStringToken}},
|
|
|
|
{`key = "multi-word-string"`, []Token{IdentifierToken, EqualsToken, QuotedStringToken, EndOfStringToken}},
|
Index arbitrary labels (#317)
* Add more fields to index when sql-caching is on.
* Restore the gvkKey helper, add event fields.
The UI team wasn't sure whether the event fields should go in the empty-string group or in 'events.k8s.io',
so let's go with both until/unless specified otherwise.
* More fixes to the fields to index:
- Remove the erroneously added management.cattle.io.nodes fields
- Use the builtin Event class, not events.k8s.io (by looking at the dashboard client code)
* Start on the virtual-field work.
* Map `Event.type` to `Event._type` for indexing.
* Add a unit test for field replacement for Event.type
* Add label processing.
* Don't test for transformation of event objects in the common module.
* Parse metadata.label queries differently.
* Improve a variable name that turned out to not be temporary.
* No need to specifically cache certain labels, as all are now cached.
* Add a test to verify simple label (m.labels.foo=blah) queries work.
* 'addLabelFields' never returns an error.
* Delete superseded function.
* Was calling 'addLabelFields' one time too many.
* Start using k8s ParseToRequirements
* Pull in the k8s parser.
* Successfully test for quotation marks.
* Add quoted strings to the lexer.
* Move to a forked k8s label lexer to include non-label tests.
* Improve and test the way quoted strings in the query are detected.
* Reinstate the original Apache license in the derived code.
Following clause 4.3 of the Apache license:
"You must cause any modified files to carry prominent notices stating that You changed the files..."
* Ignore case for operators.
* Test IN multiple-target-values
* Test the not-in operator.
* Ignore case for operators.
SQL is case-insensitive on field names and values, so this just adds consistency.
* Added tests for parsing EXISTS and NOT-EXISTS queries.
* Parse less-than and greater-than ops
* Lasso's `CacheFor` now takes a `watchable` argument.
* Support 'gt' and 'lt' as synonyms for '<' and '>'.
I see both types of operators being bandied about -- it's easy to support the aliases.
* typo fix
* Have the filter parser allow exist tests only on labels.
Also reduce the case where there's no namespace function.
* Specify hard-wired fields to index alphabetically.
* Remove unused variable.
* Parser: 'metadata.labels[FIELD]' is valid
* Pull in new gvk fields from main (and keep in alpha order).
* Fixed a couple of drops done during the last rebase.
* Add a reminder to keep the entries in alpha order.
* Test TransformLabels
* Remove TransformLabels
* Remove unused/unneeded code.
* Describe diffs between our label-selector parser and upstream's.
* Use the merged lasso 46333 work.
* Drop unused field.
* Tighten up the code.
* Specify which commit the label selector parser is based on.
* Allow both single-quoted and double-quoted value matching, doc difference.
* More review-driven changes:
- Stricter processing of m.l.name keys:
Require ending close-bracket for a start-bracket
- Comment fix
- Moving sql processing from lasso to steve: some changes missed in rebase
* Drop support for double-quotes for string values.
For now on only single-quotes (or none where possible) are allowed.
* Renaming and dropping an init block.
* Quoted strings are dropped from the filter queries
In particular, label values have a specific syntax: they must
start and end with a letter, and their innards may contain
only alnums '.', '-' and '_'. So there's no need for quoting.
And that means now that `=` and `==` do exact matches,
and the `~` operator does a partial match.
`!=` and `!~` negate -- note that `!~` is a stricter operation than `!=`,
in that given a set of possible string values, `!=` will accept more
of them than `!~`. Maybe I shouldn't have gone here, but these operators
reminded me of learning about `nicht durfen` and `nicht sollen` in German,
or something like that.
* Move a constant definition to the module level.
* Remove commented-out code.
* Remove unused func and adjacent redundant comment.
2025-01-30 19:57:23 +00:00
|
|
|
}
|
|
|
|
for _, v := range testcases {
|
|
|
|
p := &Parser{l: &Lexer{s: v.s, pos: 0}, position: 0}
|
|
|
|
p.scan()
|
|
|
|
if len(p.scannedItems) != len(v.t) {
|
|
|
|
t.Errorf("Expected %d items for test %s, found %d", len(v.t), v.s, len(p.scannedItems))
|
|
|
|
}
|
2025-05-13 18:40:54 +00:00
|
|
|
for i, entry := range v.t {
|
|
|
|
token, _ := p.consume(KeyAndOperator)
|
Index arbitrary labels (#317)
* Add more fields to index when sql-caching is on.
* Restore the gvkKey helper, add event fields.
The UI team wasn't sure whether the event fields should go in the empty-string group or in 'events.k8s.io',
so let's go with both until/unless specified otherwise.
* More fixes to the fields to index:
- Remove the erroneously added management.cattle.io.nodes fields
- Use the builtin Event class, not events.k8s.io (by looking at the dashboard client code)
* Start on the virtual-field work.
* Map `Event.type` to `Event._type` for indexing.
* Add a unit test for field replacement for Event.type
* Add label processing.
* Don't test for transformation of event objects in the common module.
* Parse metadata.label queries differently.
* Improve a variable name that turned out to not be temporary.
* No need to specifically cache certain labels, as all are now cached.
* Add a test to verify simple label (m.labels.foo=blah) queries work.
* 'addLabelFields' never returns an error.
* Delete superseded function.
* Was calling 'addLabelFields' one time too many.
* Start using k8s ParseToRequirements
* Pull in the k8s parser.
* Successfully test for quotation marks.
* Add quoted strings to the lexer.
* Move to a forked k8s label lexer to include non-label tests.
* Improve and test the way quoted strings in the query are detected.
* Reinstate the original Apache license in the derived code.
Following clause 4.3 of the Apache license:
"You must cause any modified files to carry prominent notices stating that You changed the files..."
* Ignore case for operators.
* Test IN multiple-target-values
* Test the not-in operator.
* Ignore case for operators.
SQL is case-insensitive on field names and values, so this just adds consistency.
* Added tests for parsing EXISTS and NOT-EXISTS queries.
* Parse less-than and greater-than ops
* Lasso's `CacheFor` now takes a `watchable` argument.
* Support 'gt' and 'lt' as synonyms for '<' and '>'.
I see both types of operators being bandied about -- it's easy to support the aliases.
* typo fix
* Have the filter parser allow exist tests only on labels.
Also reduce the case where there's no namespace function.
* Specify hard-wired fields to index alphabetically.
* Remove unused variable.
* Parser: 'metadata.labels[FIELD]' is valid
* Pull in new gvk fields from main (and keep in alpha order).
* Fixed a couple of drops done during the last rebase.
* Add a reminder to keep the entries in alpha order.
* Test TransformLabels
* Remove TransformLabels
* Remove unused/unneeded code.
* Describe diffs between our label-selector parser and upstream's.
* Use the merged lasso 46333 work.
* Drop unused field.
* Tighten up the code.
* Specify which commit the label selector parser is based on.
* Allow both single-quoted and double-quoted value matching, doc difference.
* More review-driven changes:
- Stricter processing of m.l.name keys:
Require ending close-bracket for a start-bracket
- Comment fix
- Moving sql processing from lasso to steve: some changes missed in rebase
* Drop support for double-quotes for string values.
For now on only single-quotes (or none where possible) are allowed.
* Renaming and dropping an init block.
* Quoted strings are dropped from the filter queries
In particular, label values have a specific syntax: they must
start and end with a letter, and their innards may contain
only alnums '.', '-' and '_'. So there's no need for quoting.
And that means now that `=` and `==` do exact matches,
and the `~` operator does a partial match.
`!=` and `!~` negate -- note that `!~` is a stricter operation than `!=`,
in that given a set of possible string values, `!=` will accept more
of them than `!~`. Maybe I shouldn't have gone here, but these operators
reminded me of learning about `nicht durfen` and `nicht sollen` in German,
or something like that.
* Move a constant definition to the module level.
* Remove commented-out code.
* Remove unused func and adjacent redundant comment.
2025-01-30 19:57:23 +00:00
|
|
|
if token == EndOfStringToken {
|
2025-05-13 18:40:54 +00:00
|
|
|
if i != len(v.t)-1 {
|
|
|
|
t.Errorf("Expected end of string token at position %d for test '%s', but length is %d", i, v.s, len(v.t))
|
|
|
|
}
|
Index arbitrary labels (#317)
* Add more fields to index when sql-caching is on.
* Restore the gvkKey helper, add event fields.
The UI team wasn't sure whether the event fields should go in the empty-string group or in 'events.k8s.io',
so let's go with both until/unless specified otherwise.
* More fixes to the fields to index:
- Remove the erroneously added management.cattle.io.nodes fields
- Use the builtin Event class, not events.k8s.io (by looking at the dashboard client code)
* Start on the virtual-field work.
* Map `Event.type` to `Event._type` for indexing.
* Add a unit test for field replacement for Event.type
* Add label processing.
* Don't test for transformation of event objects in the common module.
* Parse metadata.label queries differently.
* Improve a variable name that turned out to not be temporary.
* No need to specifically cache certain labels, as all are now cached.
* Add a test to verify simple label (m.labels.foo=blah) queries work.
* 'addLabelFields' never returns an error.
* Delete superseded function.
* Was calling 'addLabelFields' one time too many.
* Start using k8s ParseToRequirements
* Pull in the k8s parser.
* Successfully test for quotation marks.
* Add quoted strings to the lexer.
* Move to a forked k8s label lexer to include non-label tests.
* Improve and test the way quoted strings in the query are detected.
* Reinstate the original Apache license in the derived code.
Following clause 4.3 of the Apache license:
"You must cause any modified files to carry prominent notices stating that You changed the files..."
* Ignore case for operators.
* Test IN multiple-target-values
* Test the not-in operator.
* Ignore case for operators.
SQL is case-insensitive on field names and values, so this just adds consistency.
* Added tests for parsing EXISTS and NOT-EXISTS queries.
* Parse less-than and greater-than ops
* Lasso's `CacheFor` now takes a `watchable` argument.
* Support 'gt' and 'lt' as synonyms for '<' and '>'.
I see both types of operators being bandied about -- it's easy to support the aliases.
* typo fix
* Have the filter parser allow exist tests only on labels.
Also reduce the case where there's no namespace function.
* Specify hard-wired fields to index alphabetically.
* Remove unused variable.
* Parser: 'metadata.labels[FIELD]' is valid
* Pull in new gvk fields from main (and keep in alpha order).
* Fixed a couple of drops done during the last rebase.
* Add a reminder to keep the entries in alpha order.
* Test TransformLabels
* Remove TransformLabels
* Remove unused/unneeded code.
* Describe diffs between our label-selector parser and upstream's.
* Use the merged lasso 46333 work.
* Drop unused field.
* Tighten up the code.
* Specify which commit the label selector parser is based on.
* Allow both single-quoted and double-quoted value matching, doc difference.
* More review-driven changes:
- Stricter processing of m.l.name keys:
Require ending close-bracket for a start-bracket
- Comment fix
- Moving sql processing from lasso to steve: some changes missed in rebase
* Drop support for double-quotes for string values.
For now on only single-quotes (or none where possible) are allowed.
* Renaming and dropping an init block.
* Quoted strings are dropped from the filter queries
In particular, label values have a specific syntax: they must
start and end with a letter, and their innards may contain
only alnums '.', '-' and '_'. So there's no need for quoting.
And that means now that `=` and `==` do exact matches,
and the `~` operator does a partial match.
`!=` and `!~` negate -- note that `!~` is a stricter operation than `!=`,
in that given a set of possible string values, `!=` will accept more
of them than `!~`. Maybe I shouldn't have gone here, but these operators
reminded me of learning about `nicht durfen` and `nicht sollen` in German,
or something like that.
* Move a constant definition to the module level.
* Remove commented-out code.
* Remove unused func and adjacent redundant comment.
2025-01-30 19:57:23 +00:00
|
|
|
break
|
|
|
|
}
|
2025-05-13 18:40:54 +00:00
|
|
|
if token != entry {
|
|
|
|
t.Errorf("Expected token %v at position %d for test '%s', but got %v", entry, i, v.s, token)
|
Index arbitrary labels (#317)
* Add more fields to index when sql-caching is on.
* Restore the gvkKey helper, add event fields.
The UI team wasn't sure whether the event fields should go in the empty-string group or in 'events.k8s.io',
so let's go with both until/unless specified otherwise.
* More fixes to the fields to index:
- Remove the erroneously added management.cattle.io.nodes fields
- Use the builtin Event class, not events.k8s.io (by looking at the dashboard client code)
* Start on the virtual-field work.
* Map `Event.type` to `Event._type` for indexing.
* Add a unit test for field replacement for Event.type
* Add label processing.
* Don't test for transformation of event objects in the common module.
* Parse metadata.label queries differently.
* Improve a variable name that turned out to not be temporary.
* No need to specifically cache certain labels, as all are now cached.
* Add a test to verify simple label (m.labels.foo=blah) queries work.
* 'addLabelFields' never returns an error.
* Delete superseded function.
* Was calling 'addLabelFields' one time too many.
* Start using k8s ParseToRequirements
* Pull in the k8s parser.
* Successfully test for quotation marks.
* Add quoted strings to the lexer.
* Move to a forked k8s label lexer to include non-label tests.
* Improve and test the way quoted strings in the query are detected.
* Reinstate the original Apache license in the derived code.
Following clause 4.3 of the Apache license:
"You must cause any modified files to carry prominent notices stating that You changed the files..."
* Ignore case for operators.
* Test IN multiple-target-values
* Test the not-in operator.
* Ignore case for operators.
SQL is case-insensitive on field names and values, so this just adds consistency.
* Added tests for parsing EXISTS and NOT-EXISTS queries.
* Parse less-than and greater-than ops
* Lasso's `CacheFor` now takes a `watchable` argument.
* Support 'gt' and 'lt' as synonyms for '<' and '>'.
I see both types of operators being bandied about -- it's easy to support the aliases.
* typo fix
* Have the filter parser allow exist tests only on labels.
Also reduce the case where there's no namespace function.
* Specify hard-wired fields to index alphabetically.
* Remove unused variable.
* Parser: 'metadata.labels[FIELD]' is valid
* Pull in new gvk fields from main (and keep in alpha order).
* Fixed a couple of drops done during the last rebase.
* Add a reminder to keep the entries in alpha order.
* Test TransformLabels
* Remove TransformLabels
* Remove unused/unneeded code.
* Describe diffs between our label-selector parser and upstream's.
* Use the merged lasso 46333 work.
* Drop unused field.
* Tighten up the code.
* Specify which commit the label selector parser is based on.
* Allow both single-quoted and double-quoted value matching, doc difference.
* More review-driven changes:
- Stricter processing of m.l.name keys:
Require ending close-bracket for a start-bracket
- Comment fix
- Moving sql processing from lasso to steve: some changes missed in rebase
* Drop support for double-quotes for string values.
For now on only single-quotes (or none where possible) are allowed.
* Renaming and dropping an init block.
* Quoted strings are dropped from the filter queries
In particular, label values have a specific syntax: they must
start and end with a letter, and their innards may contain
only alnums '.', '-' and '_'. So there's no need for quoting.
And that means now that `=` and `==` do exact matches,
and the `~` operator does a partial match.
`!=` and `!~` negate -- note that `!~` is a stricter operation than `!=`,
in that given a set of possible string values, `!=` will accept more
of them than `!~`. Maybe I shouldn't have gone here, but these operators
reminded me of learning about `nicht durfen` and `nicht sollen` in German,
or something like that.
* Move a constant definition to the module level.
* Remove commented-out code.
* Remove unused func and adjacent redundant comment.
2025-01-30 19:57:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseOperator(t *testing.T) {
|
|
|
|
testcases := []struct {
|
|
|
|
token string
|
|
|
|
expectedError error
|
|
|
|
}{
|
|
|
|
{"in", nil},
|
|
|
|
{"=", nil},
|
|
|
|
{"==", nil},
|
|
|
|
{"~", nil},
|
|
|
|
{">", nil},
|
|
|
|
{"<", nil},
|
|
|
|
{"lt", nil},
|
|
|
|
{"gt", nil},
|
|
|
|
{"notin", nil},
|
|
|
|
{"!=", nil},
|
|
|
|
{"!~", nil},
|
|
|
|
{"!", fmt.Errorf("found '%s', expected: %v", selection.DoesNotExist, strings.Join(binaryOperators, ", "))},
|
|
|
|
{"exists", fmt.Errorf("found '%s', expected: %v", selection.Exists, strings.Join(binaryOperators, ", "))},
|
|
|
|
{"(", fmt.Errorf("found '%s', expected: %v", "(", strings.Join(binaryOperators, ", "))},
|
|
|
|
}
|
|
|
|
for _, testcase := range testcases {
|
|
|
|
p := &Parser{l: &Lexer{s: testcase.token, pos: 0}, position: 0}
|
|
|
|
p.scan()
|
|
|
|
|
|
|
|
_, err := p.parseOperator()
|
|
|
|
if ok := reflect.DeepEqual(testcase.expectedError, err); !ok {
|
|
|
|
t.Errorf("\nexpect err [%v], \nactual err [%v]", testcase.expectedError, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Some error fields are commented out here because this fork no longer
|
|
|
|
// enforces k8s label expression lexical and length restrictions
|
|
|
|
func TestRequirementConstructor(t *testing.T) {
|
|
|
|
requirementConstructorTests := []struct {
|
|
|
|
Key string
|
|
|
|
Op selection.Operator
|
|
|
|
Vals sets.String
|
|
|
|
WantErr field.ErrorList
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
Key: "x1",
|
|
|
|
Op: selection.In,
|
|
|
|
WantErr: field.ErrorList{
|
|
|
|
&field.Error{
|
|
|
|
Type: field.ErrorTypeInvalid,
|
|
|
|
Field: "values",
|
|
|
|
BadValue: []string{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x2",
|
|
|
|
Op: selection.NotIn,
|
|
|
|
Vals: sets.NewString(),
|
|
|
|
WantErr: field.ErrorList{
|
|
|
|
&field.Error{
|
|
|
|
Type: field.ErrorTypeInvalid,
|
|
|
|
Field: "values",
|
|
|
|
BadValue: []string{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x3",
|
|
|
|
Op: selection.In,
|
|
|
|
Vals: sets.NewString("foo"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x4",
|
|
|
|
Op: selection.NotIn,
|
|
|
|
Vals: sets.NewString("foo"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x5",
|
|
|
|
Op: selection.Equals,
|
|
|
|
Vals: sets.NewString("foo", "bar"),
|
|
|
|
WantErr: field.ErrorList{
|
|
|
|
&field.Error{
|
|
|
|
Type: field.ErrorTypeInvalid,
|
|
|
|
Field: "values",
|
|
|
|
BadValue: []string{"bar", "foo"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x6",
|
|
|
|
Op: selection.Exists,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x7",
|
|
|
|
Op: selection.DoesNotExist,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x8",
|
|
|
|
Op: selection.Exists,
|
|
|
|
Vals: sets.NewString("foo"),
|
|
|
|
WantErr: field.ErrorList{
|
|
|
|
&field.Error{
|
|
|
|
Type: field.ErrorTypeInvalid,
|
|
|
|
Field: "values",
|
|
|
|
BadValue: []string{"foo"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x9",
|
|
|
|
Op: selection.In,
|
|
|
|
Vals: sets.NewString("bar"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x10",
|
|
|
|
Op: selection.In,
|
|
|
|
Vals: sets.NewString("bar"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x11",
|
|
|
|
Op: selection.GreaterThan,
|
|
|
|
Vals: sets.NewString("1"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x12",
|
|
|
|
Op: selection.LessThan,
|
|
|
|
Vals: sets.NewString("6"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x13",
|
|
|
|
Op: selection.GreaterThan,
|
|
|
|
WantErr: field.ErrorList{
|
|
|
|
&field.Error{
|
|
|
|
Type: field.ErrorTypeInvalid,
|
|
|
|
Field: "values",
|
|
|
|
BadValue: []string{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x14",
|
|
|
|
Op: selection.GreaterThan,
|
|
|
|
Vals: sets.NewString("bar"),
|
|
|
|
WantErr: field.ErrorList{
|
|
|
|
&field.Error{
|
|
|
|
Type: field.ErrorTypeInvalid,
|
|
|
|
Field: "values[0]",
|
|
|
|
BadValue: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x15",
|
|
|
|
Op: selection.LessThan,
|
|
|
|
Vals: sets.NewString("bar"),
|
|
|
|
WantErr: field.ErrorList{
|
|
|
|
&field.Error{
|
|
|
|
Type: field.ErrorTypeInvalid,
|
|
|
|
Field: "values[0]",
|
|
|
|
BadValue: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: strings.Repeat("a", 254), //breaks DNS rule that len(key) <= 253
|
|
|
|
Op: selection.Exists,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x16",
|
|
|
|
Op: selection.Equals,
|
|
|
|
Vals: sets.NewString(strings.Repeat("a", 254)),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x17",
|
|
|
|
Op: selection.Equals,
|
|
|
|
Vals: sets.NewString("a b"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x18",
|
|
|
|
Op: "unsupportedOp",
|
|
|
|
WantErr: field.ErrorList{
|
|
|
|
&field.Error{
|
|
|
|
Type: field.ErrorTypeNotSupported,
|
|
|
|
Field: "operator",
|
|
|
|
BadValue: selection.Operator("unsupportedOp"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, rc := range requirementConstructorTests {
|
|
|
|
_, err := NewRequirement(rc.Key, rc.Op, rc.Vals.List())
|
|
|
|
if diff := cmp.Diff(rc.WantErr.ToAggregate(), err, ignoreDetail); diff != "" {
|
|
|
|
t.Errorf("NewRequirement test %v returned unexpected error (-want,+got):\n%s", rc.Key, diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|