support fieldselector filter query secrets (#5300)

* support fieldselector filter query secrets

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>

* support fieldselector filter query secrets

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>

* support fieldselector filter query secrets

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>

* support fieldselector filter query secrets

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>

* support fieldselector filter query secrets

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
This commit is contained in:
nuclearwu
2022-10-26 10:14:49 +08:00
committed by GitHub
parent 1e79901241
commit 89b1b6db87
10 changed files with 956 additions and 0 deletions

View File

@@ -88,6 +88,7 @@ func AddToContainer(c *restful.Container, informerFactory informers.InformerFact
Param(webservice.QueryParameter(query.ParameterLimit, "limit").Required(false)).
Param(webservice.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("ascending=false")).
Param(webservice.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")).
Param(webservice.QueryParameter(query.ParameterFieldSelector, "field selector used for filtering, you can use the = , == and != operators with field selectors( = and == mean the same thing), e.g. fieldSelector=type=kubernetes.io/dockerconfigjson, multiple separated by comma").Required(false)).
Returns(http.StatusOK, ok, api.ListResult{}))
webservice.Route(webservice.GET("/namespaces/{namespace}/{resources}/{name}").

View File

@@ -17,13 +17,20 @@ limitations under the License.
package secret
import (
"encoding/json"
"fmt"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/selection"
"k8s.io/client-go/informers"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"github.com/oliveagle/jsonpath"
v1 "k8s.io/api/core/v1"
)
@@ -74,5 +81,55 @@ func (s *secretSearcher) filter(object runtime.Object, filter query.Filter) bool
return false
}
if filter.Field == query.ParameterFieldSelector {
return contains(secret, filter.Value)
}
return v1alpha3.DefaultObjectMetaFilter(secret.ObjectMeta, filter)
}
// implement a generic query filter to support multiple field selectors with "jsonpath.JsonPathLookup"
// https://github.com/oliveagle/jsonpath/blob/master/readme.md
func contains(secret *v1.Secret, queryValue query.Value) bool {
// call the ParseSelector function of "k8s.io/apimachinery/pkg/fields/selector.go" to validate and parse the selector
fieldSelector, err := fields.ParseSelector(string(queryValue))
if err != nil {
klog.V(4).Infof("failed parse selector error: %s", err)
return false
}
for _, requirement := range fieldSelector.Requirements() {
var negative bool
// supports '=', '==' and '!='.(e.g. ?fieldSelector=key1=value1,key2=value2)
switch requirement.Operator {
case selection.NotEquals:
negative = true
case selection.DoubleEquals:
case selection.Equals:
negative = false
}
key := requirement.Field
value := requirement.Value
var input map[string]interface{}
data, err := json.Marshal(secret)
if err != nil {
klog.V(4).Infof("failed marshal to JSON string: %s", err)
return false
}
if err = json.Unmarshal(data, &input); err != nil {
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)
return false
}
if (negative && fmt.Sprintf("%v", rawValue) != value) || (!negative && fmt.Sprintf("%v", rawValue) == value) {
continue
} else {
return false
}
}
return true
}