improve field selector

Signed-off-by: hongming <coder.scala@gmail.com>
This commit is contained in:
hongming
2025-06-11 10:47:32 +08:00
parent 4d88ed2ca1
commit 25cf3a7d10
2 changed files with 90 additions and 5 deletions

View File

@@ -7,19 +7,20 @@
package v1beta1
import (
"bytes"
"context"
"encoding/json"
"fmt"
"sort"
"strings"
"github.com/oliveagle/jsonpath"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/selection"
"k8s.io/client-go/util/jsonpath"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -244,7 +245,7 @@ func contains(object runtime.Object, queryValue query.Value) bool {
key := requirement.Field
value := requirement.Value
var input map[string]interface{}
var input interface{}
data, err := json.Marshal(object)
if err != nil {
klog.V(4).Infof("failed marshal to JSON string: %s", err)
@@ -254,11 +255,20 @@ func contains(object runtime.Object, queryValue query.Value) bool {
klog.V(4).Infof("failed unmarshal to map object: %s", err)
return false
}
rawValue, err := jsonpath.JsonPathLookup(input, "$."+key)
if err != nil {
klog.V(4).Infof("failed to lookup jsonpath: %s", err)
buf := new(bytes.Buffer)
lookup := jsonpath.New("")
lookup.AllowMissingKeys(true)
if err = lookup.Parse(fmt.Sprintf("{.%s}", key)); err != nil {
klog.V(4).Infof("failed parse jsonpath: %s", err)
return false
}
if err = lookup.Execute(buf, input); err != nil {
klog.V(4).Infof("failed execute jsonpath: %s", err)
return false
}
rawValue := buf.String()
// Values prefixed with ~ support case insensitivity. (e.g., a=~b, can hit b, B)
if strings.HasPrefix(value, "~") {

View File

@@ -0,0 +1,75 @@
package v1beta1
import (
"testing"
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/kubesphere/pkg/apiserver/query"
)
func TestContains_MatchesFieldSelector(t *testing.T) {
object := &runtime.Unknown{
Raw: []byte(`{"metadata":{"name":"test-object","namespace":"default"}}`),
}
queryValue := query.Value("metadata.name=test-object")
if !contains(object, queryValue) {
t.Errorf("Expected object to match field selector, but it did not")
}
}
func TestContains_DoesNotMatchFieldSelector(t *testing.T) {
object := &runtime.Unknown{
Raw: []byte(`{"metadata":{"name":"test-object","namespace":"default"}}`),
}
queryValue := query.Value("metadata.name=nonexistent-object")
if contains(object, queryValue) {
t.Errorf("Expected object not to match field selector, but it did")
}
}
func TestContains_InvalidFieldSelector(t *testing.T) {
object := &runtime.Unknown{
Raw: []byte(`{"metadata":{"name":"test-object","namespace":"default"}}`),
}
queryValue := query.Value("invalid-selector")
if contains(object, queryValue) {
t.Errorf("Expected object not to match invalid field selector, but it did")
}
}
func TestContains_CaseInsensitiveMatch(t *testing.T) {
object := &runtime.Unknown{
Raw: []byte(`{"metadata":{"name":"Test-Object","namespace":"default"}}`),
}
queryValue := query.Value("metadata.name=~test-object")
if !contains(object, queryValue) {
t.Errorf("Expected object to match field selector case-insensitively, but it did not")
}
}
func TestContains_EmptyObject(t *testing.T) {
object := &runtime.Unknown{
Raw: []byte(`{}`),
}
queryValue := query.Value("metadata.name=test-object")
if contains(object, queryValue) {
t.Errorf("Expected empty object not to match field selector, but it did")
}
}
func TestContains_NestedDataWithSpecialCharacters(t *testing.T) {
object := &runtime.Unknown{
Raw: []byte(`{"metadata":{"name":"test-object","annotations":{"example.com/special-key":"special-value"}}}`),
}
queryValue := query.Value(`metadata.annotations.example\.com/special-key=special-value`)
if !contains(object, queryValue) {
t.Errorf("Expected object to match field selector with nested data and special characters, but it did not")
}
}