From 5bad05aa607a5b090c9cc3580db162fdd7be8bd8 Mon Sep 17 00:00:00 2001 From: kaikaila Date: Mon, 6 Apr 2026 20:38:54 -0700 Subject: [PATCH] fix(backend): enhance case-insensitive matching for k8s CRD backend Signed-off-by: kaikaila --- backend/src/apiserver/filter/filter.go | 10 +++--- backend/src/apiserver/filter/filter_test.go | 40 +++++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/backend/src/apiserver/filter/filter.go b/backend/src/apiserver/filter/filter.go index 542cbb4ff73..29673505d5e 100644 --- a/backend/src/apiserver/filter/filter.go +++ b/backend/src/apiserver/filter/filter.go @@ -241,7 +241,7 @@ func (f *Filter) matchesFilter(getField func(string) interface{}) (bool, error) for k := range f.eq { fieldVal := fmt.Sprint(getField(k)) for _, v := range f.eq[k] { - if fieldVal != fmt.Sprint(v) { + if !strings.EqualFold(fieldVal, fmt.Sprint(v)) { return false, nil } } @@ -251,7 +251,7 @@ func (f *Filter) matchesFilter(getField func(string) interface{}) (bool, error) for k := range f.neq { fieldVal := fmt.Sprint(getField(k)) for _, v := range f.neq[k] { - if fieldVal == fmt.Sprint(v) { + if strings.EqualFold(fieldVal, fmt.Sprint(v)) { return false, nil } } @@ -283,7 +283,7 @@ func (f *Filter) matchesFilter(getField func(string) interface{}) (bool, error) return false, nil } for i := 0; i < rv.Len(); i++ { - if fieldVal == fmt.Sprint(rv.Index(i).Interface()) { + if strings.EqualFold(fieldVal, fmt.Sprint(rv.Index(i).Interface())) { inOne = true break } @@ -296,9 +296,9 @@ func (f *Filter) matchesFilter(getField func(string) interface{}) (bool, error) // SUBSTRING: all specified substrings must be present. for k := range f.substring { - fieldVal := fmt.Sprint(getField(k)) + lowerFieldVal := strings.ToLower(fmt.Sprint(getField(k))) for _, v := range f.substring[k] { - if !strings.Contains(fieldVal, fmt.Sprint(v)) { + if !strings.Contains(lowerFieldVal, strings.ToLower(fmt.Sprint(v))) { return false, nil } } diff --git a/backend/src/apiserver/filter/filter_test.go b/backend/src/apiserver/filter/filter_test.go index ab27c004053..9f0def8a74b 100644 --- a/backend/src/apiserver/filter/filter_test.go +++ b/backend/src/apiserver/filter/filter_test.go @@ -722,6 +722,26 @@ func TestFilterK8sPipelines_EQ_NEQ(t *testing.T) { if found { t.Fatalf("expected AND filter not to match when one predicate fails") } + + // EQ case-insensitive: "MY-PIPELINE" should match "my-pipeline" + eqCaseInsensitive := &Filter{eq: map[string][]interface{}{"pipelines.Name": {"MY-PIPELINE"}}} + found, err = eqCaseInsensitive.FilterK8sPipelines(k8sPipeline) + if err != nil { + t.Fatalf("unexpected error for EQ case-insensitive: %v", err) + } + if !found { + t.Fatalf("expected EQ filter to match case-insensitively") + } + + // NEQ case-insensitive: "MY-PIPELINE" should be considered equal, so NEQ should not match + neqCaseInsensitive := &Filter{neq: map[string][]interface{}{"pipelines.Name": {"MY-PIPELINE"}}} + found, err = neqCaseInsensitive.FilterK8sPipelines(k8sPipeline) + if err != nil { + t.Fatalf("unexpected error for NEQ case-insensitive: %v", err) + } + if found { + t.Fatalf("expected NEQ filter not to match when value matches case-insensitively") + } } func TestFilterK8sPipelines_IN(t *testing.T) { @@ -768,6 +788,16 @@ func TestFilterK8sPipelines_IN(t *testing.T) { if !found { t.Fatalf("expected IN multi to match when present in all lists") } + + // IN case-insensitive: "MY-PIPELINE" should match "my-pipeline" + inCaseInsensitive := &Filter{in: map[string][]interface{}{"pipelines.Name": {[]string{"a", "MY-PIPELINE"}}}} + found, err = inCaseInsensitive.FilterK8sPipelines(k8sPipeline) + if err != nil { + t.Fatalf("unexpected error for IN case-insensitive: %v", err) + } + if !found { + t.Fatalf("expected IN filter to match case-insensitively") + } } func TestFilterK8sPipelines_SUBSTRING(t *testing.T) { @@ -794,6 +824,16 @@ func TestFilterK8sPipelines_SUBSTRING(t *testing.T) { if found { t.Fatalf("expected substring filter not to match when a substring missing") } + + // IS_SUBSTRING case-insensitive: "Pipeline" should match "my-pipeline" + subCaseInsensitive := &Filter{substring: map[string][]interface{}{"pipelines.Name": {"Pipeline"}}} + found, err = subCaseInsensitive.FilterK8sPipelines(k8sPipeline) + if err != nil { + t.Fatalf("unexpected error for substring case-insensitive: %v", err) + } + if !found { + t.Fatalf("expected IS_SUBSTRING filter to match case-insensitively") + } } func TestFilterK8sPipelines_UnsupportedOps(t *testing.T) {