K8s/Storage: Register field-selector on all kinds (#79822)
Co-authored-by: Dan Cech <dcech@grafana.com>
This commit is contained in:
co-authored by
Dan Cech
parent
73715a1de9
commit
e1d387d826
@@ -324,6 +324,12 @@ func (s *service) start(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// support folder selection
|
||||
err = entitystorage.RegisterFieldSelectorSupport(Scheme)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create the server
|
||||
server, err := serverConfig.Complete().New("grafana-apiserver", genericapiserver.NewEmptyDelegate())
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
)
|
||||
|
||||
const folderAnnoKey = "grafana.app/folder"
|
||||
|
||||
type FieldRequirements struct {
|
||||
// Equals folder
|
||||
Folder *string
|
||||
}
|
||||
|
||||
func ReadFieldRequirements(selector fields.Selector) (FieldRequirements, fields.Selector, error) {
|
||||
requirements := FieldRequirements{}
|
||||
|
||||
if selector == nil {
|
||||
return requirements, selector, nil
|
||||
}
|
||||
|
||||
for _, r := range selector.Requirements() {
|
||||
switch r.Field {
|
||||
case folderAnnoKey:
|
||||
if (r.Operator != selection.Equals) && (r.Operator != selection.DoubleEquals) {
|
||||
return requirements, selector, apierrors.NewBadRequest("only equality is supported in the selectors")
|
||||
}
|
||||
folder := r.Value
|
||||
requirements.Folder = &folder
|
||||
}
|
||||
}
|
||||
|
||||
// use Transform function to remove grafana.app/folder field selector
|
||||
selector, err := selector.Transform(func(field, value string) (string, string, error) {
|
||||
switch field {
|
||||
case folderAnnoKey:
|
||||
return "", "", nil
|
||||
}
|
||||
return field, value, nil
|
||||
})
|
||||
|
||||
return requirements, selector, err
|
||||
}
|
||||
|
||||
func RegisterFieldSelectorSupport(scheme *runtime.Scheme) error {
|
||||
grafanaFieldSupport := runtime.FieldLabelConversionFunc(
|
||||
func(field, value string) (string, string, error) {
|
||||
if strings.HasPrefix(field, "grafana.app/") {
|
||||
return field, value, nil
|
||||
}
|
||||
return "", "", getBadSelectorError(field)
|
||||
},
|
||||
)
|
||||
|
||||
// Register all the internal types
|
||||
for gvk := range scheme.AllKnownTypes() {
|
||||
if strings.HasSuffix(gvk.Group, ".grafana.app") {
|
||||
err := scheme.AddFieldLabelConversionFunc(gvk, grafanaFieldSupport)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getBadSelectorError(f string) error {
|
||||
return apierrors.NewBadRequest(
|
||||
fmt.Sprintf("%q is not a known field selector: only %q works", f, folderAnnoKey),
|
||||
)
|
||||
}
|
||||
@@ -241,29 +241,16 @@ func (s *Storage) GetList(ctx context.Context, key string, opts storage.ListOpti
|
||||
}
|
||||
}
|
||||
|
||||
// translate grafana.app/folder field selector to folder condition
|
||||
fields := opts.Predicate.Field.Requirements()
|
||||
for _, f := range fields {
|
||||
if f.Field == "grafana.app/folder" {
|
||||
if f.Operator != selection.Equals {
|
||||
return apierrors.NewBadRequest("grafana.app/folder field selector only supports equality")
|
||||
}
|
||||
|
||||
// select items in the spcified folder
|
||||
req.Folder = f.Value
|
||||
}
|
||||
}
|
||||
|
||||
// use Transform function to remove grafana.app/folder field selector
|
||||
opts.Predicate.Field, err = opts.Predicate.Field.Transform(func(field, value string) (string, string, error) {
|
||||
if field == "grafana.app/folder" {
|
||||
return "", "", nil
|
||||
}
|
||||
return field, value, nil
|
||||
})
|
||||
// translate grafana.app/folder field selector to the folder condition
|
||||
fieldRequirements, fieldSelector, err := ReadFieldRequirements(opts.Predicate.Field)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if fieldRequirements.Folder != nil {
|
||||
req.Folder = *fieldRequirements.Folder
|
||||
}
|
||||
// Update the field selector to remove the unneeded selectors
|
||||
opts.Predicate.Field = fieldSelector
|
||||
|
||||
rsp, err := s.store.List(ctx, req)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user