* Provisioning: Add fieldSelector for Repository by spec.connection.name This change adds the ability to filter repositories by their connection name using Kubernetes field selectors, enabling queries like: kubectl get repositories --field-selector spec.connection.name=my-connection Implementation: - Add RepositoryGetAttrs and RepositoryToSelectableFields functions - Register field label conversion for spec.connection.name in InstallSchema - Extend generic storage to support custom selectable fields via NewRegistryStoreWithSelectableFields - Add unit tests for repository field functions - Add integration tests for field selector functionality * Simplify predicateFunc handling with custom attrFunc Remove unnecessary custom predicateFunc wrapper when using a custom GetAttrs function. When attrFunc is provided via StoreOptions, passing nil for predicateFunc allows the default behavior to create the appropriate SelectionPredicate automatically. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
84 lines
3.4 KiB
Go
84 lines
3.4 KiB
Go
package generic
|
|
|
|
import (
|
|
"k8s.io/apimachinery/pkg/fields"
|
|
"k8s.io/apimachinery/pkg/labels"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apiserver/pkg/registry/generic"
|
|
"k8s.io/apiserver/pkg/registry/generic/registry"
|
|
"k8s.io/apiserver/pkg/storage"
|
|
|
|
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
|
)
|
|
|
|
// SelectableFieldsOptions allows customizing field selector behavior for a resource.
|
|
type SelectableFieldsOptions struct {
|
|
// GetAttrs returns labels and fields for the object.
|
|
// If nil, the default GetAttrs is used which only exposes metadata.name.
|
|
GetAttrs func(obj runtime.Object) (labels.Set, fields.Set, error)
|
|
}
|
|
|
|
func NewRegistryStore(scheme *runtime.Scheme, resourceInfo utils.ResourceInfo, optsGetter generic.RESTOptionsGetter) (*registry.Store, error) {
|
|
return NewRegistryStoreWithSelectableFields(scheme, resourceInfo, optsGetter, SelectableFieldsOptions{})
|
|
}
|
|
|
|
// NewRegistryStoreWithSelectableFields creates a registry store with custom selectable fields support.
|
|
// Use this when you need to filter resources by custom fields like spec.connection.name.
|
|
func NewRegistryStoreWithSelectableFields(scheme *runtime.Scheme, resourceInfo utils.ResourceInfo, optsGetter generic.RESTOptionsGetter, fieldOpts SelectableFieldsOptions) (*registry.Store, error) {
|
|
gv := resourceInfo.GroupVersion()
|
|
gv.Version = runtime.APIVersionInternal
|
|
strategy := NewStrategy(scheme, gv)
|
|
if resourceInfo.IsClusterScoped() {
|
|
strategy = strategy.WithClusterScope()
|
|
}
|
|
|
|
// Use custom GetAttrs if provided, otherwise use default
|
|
var attrFunc storage.AttrFunc
|
|
var predicateFunc func(label labels.Selector, field fields.Selector) storage.SelectionPredicate
|
|
if fieldOpts.GetAttrs != nil {
|
|
attrFunc = fieldOpts.GetAttrs
|
|
// Pass nil predicateFunc to use default behavior with custom attrFunc
|
|
predicateFunc = nil
|
|
} else {
|
|
attrFunc = GetAttrs
|
|
predicateFunc = Matcher
|
|
}
|
|
|
|
store := ®istry.Store{
|
|
NewFunc: resourceInfo.NewFunc,
|
|
NewListFunc: resourceInfo.NewListFunc,
|
|
KeyRootFunc: KeyRootFunc(resourceInfo.GroupResource()),
|
|
KeyFunc: NamespaceKeyFunc(resourceInfo.GroupResource()),
|
|
PredicateFunc: predicateFunc,
|
|
DefaultQualifiedResource: resourceInfo.GroupResource(),
|
|
SingularQualifiedResource: resourceInfo.SingularGroupResource(),
|
|
TableConvertor: resourceInfo.TableConverter(),
|
|
CreateStrategy: strategy,
|
|
UpdateStrategy: strategy,
|
|
DeleteStrategy: strategy,
|
|
}
|
|
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: attrFunc}
|
|
if err := store.CompleteWithOptions(options); err != nil {
|
|
return nil, err
|
|
}
|
|
return store, nil
|
|
}
|
|
|
|
func NewCompleteRegistryStore(scheme *runtime.Scheme, resourceInfo utils.ResourceInfo, optsGetter generic.RESTOptionsGetter) (*registry.Store, error) {
|
|
registryStore, err := NewRegistryStore(scheme, resourceInfo, optsGetter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
strategy := NewCompleteStrategy(scheme, resourceInfo.GroupVersion())
|
|
registryStore.CreateStrategy = strategy
|
|
registryStore.UpdateStrategy = strategy
|
|
registryStore.DeleteStrategy = strategy
|
|
return registryStore, nil
|
|
}
|
|
|
|
func NewRegistryStatusStore(scheme *runtime.Scheme, specStore *registry.Store) *StatusREST {
|
|
gv := specStore.New().GetObjectKind().GroupVersionKind().GroupVersion()
|
|
strategy := NewStatusStrategy(scheme, gv)
|
|
return NewStatusREST(specStore, strategy)
|
|
}
|