From c805566575cfe5832d551fa03dae9b827831f4ee Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Mon, 15 May 2023 12:57:27 +0530 Subject: [PATCH] Allow field KV general matching Currently all matching support is limited to map-list representations; this adds support for a more general "key:value" based matching expression for any `interface{}` field (non-map-list-like). --- docs/customresourcestate-metrics.md | 3 +++ pkg/customresourcestate/registry_factory.go | 10 ++++++++++ pkg/customresourcestate/registry_factory_test.go | 9 +++++++++ 3 files changed, 22 insertions(+) diff --git a/docs/customresourcestate-metrics.md b/docs/customresourcestate-metrics.md index 0ed35f494b..b0e1edd775 100644 --- a/docs/customresourcestate-metrics.md +++ b/docs/customresourcestate-metrics.md @@ -480,4 +480,7 @@ Examples: # if the value to be matched is a number or boolean, the value is compared as a number or boolean [status, conditions, "[value=66]", name] # status.conditions[1].name = "b" + +# For generally matching against a field in an object schema, use the following syntax: +[metadata, annotations, "bar:baz"] # metadata.annotations["bar:baz"] = "baz" (if present, ignored otherwise) ``` diff --git a/pkg/customresourcestate/registry_factory.go b/pkg/customresourcestate/registry_factory.go index 15ebdcbe72..a9c6a0a23f 100644 --- a/pkg/customresourcestate/registry_factory.go +++ b/pkg/customresourcestate/registry_factory.go @@ -613,6 +613,16 @@ func compilePath(path []string) (out valuePath, _ error) { part: part, op: func(m interface{}) interface{} { if mp, ok := m.(map[string]interface{}); ok { + kv := strings.Split(part, ":") + if len(kv) == 2 /* k:v */ { + key := kv[0] + val := kv[1] + if v, ok := mp[key]; ok { + if v == val { + return v + } + } + } return mp[part] } else if s, ok := m.([]interface{}); ok { i, err := strconv.Atoi(part) diff --git a/pkg/customresourcestate/registry_factory_test.go b/pkg/customresourcestate/registry_factory_test.go index d68f22b617..0f919df817 100644 --- a/pkg/customresourcestate/registry_factory_test.go +++ b/pkg/customresourcestate/registry_factory_test.go @@ -332,6 +332,15 @@ func Test_values(t *testing.T) { newEachValue(t, 0, "type", "Provisioned"), newEachValue(t, 1, "type", "Ready"), }}, + {name: ": expression matching", each: &compiledInfo{ + compiledCommon: compiledCommon{ + labelFromPath: map[string]valuePath{ + "bar": mustCompilePath(t, "metadata", "annotations", "bar:baz"), + }, + }, + }, wantResult: []eachValue{ + newEachValue(t, 1, "bar", "baz"), + }}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {