1
0
mirror of https://github.com/rancher/steve.git synced 2025-09-01 15:37:31 +00:00

[v2.9] Virtual Resource filters (#288)

Adds logic which adds virtual fields resources. This allows these fields
to be sorted/filtered on when the SQL cache is enabled. Id and
metadata.state.name were added as the first two fields.

Co-authored-by: Michael Bolot <michael.bolot@suse.com>
This commit is contained in:
Silvio Moioli
2024-10-02 14:59:54 +02:00
committed by GitHub
parent aacb5b82de
commit dd27bd0c8d
15 changed files with 611 additions and 122 deletions

View File

@@ -15,6 +15,15 @@ import (
"sync"
"github.com/pkg/errors"
"github.com/rancher/steve/pkg/attributes"
"github.com/rancher/steve/pkg/resources/common"
"github.com/rancher/steve/pkg/resources/virtual"
virtualCommon "github.com/rancher/steve/pkg/resources/virtual/common"
metricsStore "github.com/rancher/steve/pkg/stores/metrics"
"github.com/rancher/steve/pkg/stores/sqlpartition/listprocessor"
"github.com/rancher/steve/pkg/stores/sqlproxy/tablelistconvert"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
"k8s.io/apimachinery/pkg/api/meta"
@@ -39,11 +48,7 @@ import (
"github.com/rancher/wrangler/v3/pkg/schemas/validation"
"github.com/rancher/wrangler/v3/pkg/summary"
"github.com/rancher/steve/pkg/attributes"
"github.com/rancher/steve/pkg/resources/common"
metricsStore "github.com/rancher/steve/pkg/stores/metrics"
"github.com/rancher/steve/pkg/stores/sqlpartition/listprocessor"
"github.com/rancher/steve/pkg/stores/sqlproxy/tablelistconvert"
"k8s.io/client-go/tools/cache"
)
const (
@@ -63,6 +68,10 @@ var (
"management.cattle.io_v3_Node": {{`status`, `nodeName`}},
}
commonIndexFields = [][]string{
{`id`},
{`metadata`, `state`, `name`},
}
baseNSSchema = types.APISchema{
Schema: &schemas.Schema{
Attributes: map[string]interface{}{
@@ -124,29 +133,35 @@ type RelationshipNotifier interface {
OnInboundRelationshipChange(ctx context.Context, schema *types.APISchema, namespace string) <-chan *summary.Relationship
}
type TransformBuilder interface {
GetTransformFunc(gvk schema.GroupVersionKind) cache.TransformFunc
}
type Store struct {
clientGetter ClientGetter
notifier RelationshipNotifier
cacheFactory CacheFactory
cfInitializer CacheFactoryInitializer
namespaceCache Cache
lock sync.Mutex
columnSetter SchemaColumnSetter
clientGetter ClientGetter
notifier RelationshipNotifier
cacheFactory CacheFactory
cfInitializer CacheFactoryInitializer
namespaceCache Cache
lock sync.Mutex
columnSetter SchemaColumnSetter
transformBuilder TransformBuilder
}
type CacheFactoryInitializer func() (CacheFactory, error)
type CacheFactory interface {
CacheFor(fields [][]string, client dynamic.ResourceInterface, gvk schema.GroupVersionKind, namespaced bool) (factory.Cache, error)
CacheFor(fields [][]string, transform cache.TransformFunc, client dynamic.ResourceInterface, gvk schema.GroupVersionKind, namespaced bool) (factory.Cache, error)
Reset() error
}
// NewProxyStore returns a Store implemented directly on top of kubernetes.
func NewProxyStore(c SchemaColumnSetter, clientGetter ClientGetter, notifier RelationshipNotifier, factory CacheFactory) (*Store, error) {
func NewProxyStore(c SchemaColumnSetter, clientGetter ClientGetter, notifier RelationshipNotifier, scache virtualCommon.SummaryCache, factory CacheFactory) (*Store, error) {
store := &Store{
clientGetter: clientGetter,
notifier: notifier,
columnSetter: c,
clientGetter: clientGetter,
notifier: notifier,
columnSetter: c,
transformBuilder: virtual.NewTransformBuilder(scache),
}
if factory == nil {
@@ -203,14 +218,18 @@ func (s *Store) initializeNamespaceCache() error {
return err
}
gvk := attributes.GVK(&nsSchema)
// get fields from schema's columns
fields := getFieldsFromSchema(&nsSchema)
// get any type-specific fields that steve is interested in
fields = append(fields, getFieldForGVK(attributes.GVK(&nsSchema))...)
fields = append(fields, getFieldForGVK(gvk)...)
// get the type-specifc transform func
transformFunc := s.transformBuilder.GetTransformFunc(gvk)
// get the ns informer
nsInformer, err := s.cacheFactory.CacheFor(fields, &tablelistconvert.Client{ResourceInterface: client}, attributes.GVK(&nsSchema), false)
nsInformer, err := s.cacheFactory.CacheFor(fields, transformFunc, &tablelistconvert.Client{ResourceInterface: client}, attributes.GVK(&nsSchema), false)
if err != nil {
return err
}
@@ -220,7 +239,13 @@ func (s *Store) initializeNamespaceCache() error {
}
func getFieldForGVK(gvk schema.GroupVersionKind) [][]string {
return typeSpecificIndexedFields[keyFromGVK(gvk)]
fields := [][]string{}
fields = append(fields, commonIndexFields...)
typeFields := typeSpecificIndexedFields[keyFromGVK(gvk)]
if typeFields != nil {
fields = append(fields, typeFields...)
}
return fields
}
func keyFromGVK(gvk schema.GroupVersionKind) string {
@@ -639,10 +664,12 @@ func (s *Store) ListByPartitions(apiOp *types.APIRequest, schema *types.APISchem
if err != nil {
return nil, 0, "", err
}
gvk := attributes.GVK(schema)
fields := getFieldsFromSchema(schema)
fields = append(fields, getFieldForGVK(attributes.GVK(schema))...)
fields = append(fields, getFieldForGVK(gvk)...)
transformFunc := s.transformBuilder.GetTransformFunc(gvk)
inf, err := s.cacheFactory.CacheFor(fields, &tablelistconvert.Client{ResourceInterface: client}, attributes.GVK(schema), attributes.Namespaced(schema))
inf, err := s.cacheFactory.CacheFor(fields, transformFunc, &tablelistconvert.Client{ResourceInterface: client}, attributes.GVK(schema), attributes.Namespaced(schema))
if err != nil {
return nil, 0, "", err
}