mirror of
https://github.com/rancher/steve.git
synced 2025-09-05 17:30:39 +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:
@@ -41,7 +41,7 @@ import (
|
||||
clientgotesting "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
//go:generate mockgen --build_flags=--mod=mod -package sqlproxy -destination ./proxy_mocks_test.go github.com/rancher/steve/pkg/stores/sqlproxy Cache,ClientGetter,CacheFactory,SchemaColumnSetter,RelationshipNotifier
|
||||
//go:generate mockgen --build_flags=--mod=mod -package sqlproxy -destination ./proxy_mocks_test.go github.com/rancher/steve/pkg/stores/sqlproxy Cache,ClientGetter,CacheFactory,SchemaColumnSetter,RelationshipNotifier,TransformBuilder
|
||||
//go:generate mockgen --build_flags=--mod=mod -package sqlproxy -destination ./sql_informer_mocks_test.go github.com/rancher/lasso/pkg/cache/sql/informer ByOptionsLister
|
||||
//go:generate mockgen --build_flags=--mod=mod -package sqlproxy -destination ./dynamic_mocks_test.go k8s.io/client-go/dynamic ResourceInterface
|
||||
|
||||
@@ -82,9 +82,9 @@ func TestNewProxyStore(t *testing.T) {
|
||||
nsSchema := baseNSSchema
|
||||
scc.EXPECT().SetColumns(context.Background(), &nsSchema).Return(nil)
|
||||
cg.EXPECT().TableAdminClient(nil, &nsSchema, "", &WarningBuffer{}).Return(ri, nil)
|
||||
cf.EXPECT().CacheFor([][]string{{"metadata", "labels[field.cattle.io/projectId]"}}, &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(&nsSchema), false).Return(c, nil)
|
||||
cf.EXPECT().CacheFor([][]string{{`id`}, {`metadata`, `state`, `name`}, {"metadata", "labels[field.cattle.io/projectId]"}}, gomock.Any(), &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(&nsSchema), false).Return(c, nil)
|
||||
|
||||
s, err := NewProxyStore(scc, cg, rn, cf)
|
||||
s, err := NewProxyStore(scc, cg, rn, nil, cf)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, scc, s.columnSetter)
|
||||
assert.Equal(t, cg, s.clientGetter)
|
||||
@@ -105,7 +105,7 @@ func TestNewProxyStore(t *testing.T) {
|
||||
nsSchema := baseNSSchema
|
||||
scc.EXPECT().SetColumns(context.Background(), &nsSchema).Return(fmt.Errorf("error"))
|
||||
|
||||
s, err := NewProxyStore(scc, cg, rn, cf)
|
||||
s, err := NewProxyStore(scc, cg, rn, nil, cf)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, scc, s.columnSetter)
|
||||
assert.Equal(t, cg, s.clientGetter)
|
||||
@@ -127,7 +127,7 @@ func TestNewProxyStore(t *testing.T) {
|
||||
scc.EXPECT().SetColumns(context.Background(), &nsSchema).Return(nil)
|
||||
cg.EXPECT().TableAdminClient(nil, &nsSchema, "", &WarningBuffer{}).Return(nil, fmt.Errorf("error"))
|
||||
|
||||
s, err := NewProxyStore(scc, cg, rn, cf)
|
||||
s, err := NewProxyStore(scc, cg, rn, nil, cf)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, scc, s.columnSetter)
|
||||
assert.Equal(t, cg, s.clientGetter)
|
||||
@@ -149,9 +149,9 @@ func TestNewProxyStore(t *testing.T) {
|
||||
nsSchema := baseNSSchema
|
||||
scc.EXPECT().SetColumns(context.Background(), &nsSchema).Return(nil)
|
||||
cg.EXPECT().TableAdminClient(nil, &nsSchema, "", &WarningBuffer{}).Return(ri, nil)
|
||||
cf.EXPECT().CacheFor([][]string{{"metadata", "labels[field.cattle.io/projectId]"}}, &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(&nsSchema), false).Return(factory.Cache{}, fmt.Errorf("error"))
|
||||
cf.EXPECT().CacheFor([][]string{{`id`}, {`metadata`, `state`, `name`}, {"metadata", "labels[field.cattle.io/projectId]"}}, gomock.Any(), &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(&nsSchema), false).Return(factory.Cache{}, fmt.Errorf("error"))
|
||||
|
||||
s, err := NewProxyStore(scc, cg, rn, cf)
|
||||
s, err := NewProxyStore(scc, cg, rn, nil, cf)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, scc, s.columnSetter)
|
||||
assert.Equal(t, cg, s.clientGetter)
|
||||
@@ -181,6 +181,7 @@ func TestListByPartitions(t *testing.T) {
|
||||
cf := NewMockCacheFactory(gomock.NewController(t))
|
||||
ri := NewMockResourceInterface(gomock.NewController(t))
|
||||
bloi := NewMockByOptionsLister(gomock.NewController(t))
|
||||
tb := NewMockTransformBuilder(gomock.NewController(t))
|
||||
inf := &informer.Informer{
|
||||
ByOptionsLister: bloi,
|
||||
}
|
||||
@@ -188,9 +189,10 @@ func TestListByPartitions(t *testing.T) {
|
||||
ByOptionsLister: inf,
|
||||
}
|
||||
s := &Store{
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
transformBuilder: tb,
|
||||
}
|
||||
var partitions []partition.Partition
|
||||
req := &types.APIRequest{
|
||||
@@ -238,7 +240,8 @@ func TestListByPartitions(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
cg.EXPECT().TableAdminClient(req, schema, "", &WarningBuffer{}).Return(ri, nil)
|
||||
// This tests that fields are being extracted from schema columns and the type specific fields map
|
||||
cf.EXPECT().CacheFor([][]string{{"some", "field"}, {"gvk", "specific", "fields"}}, &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(schema), attributes.Namespaced(schema)).Return(c, nil)
|
||||
cf.EXPECT().CacheFor([][]string{{"some", "field"}, {`id`}, {`metadata`, `state`, `name`}, {"gvk", "specific", "fields"}}, gomock.Any(), &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(schema), attributes.Namespaced(schema)).Return(c, nil)
|
||||
tb.EXPECT().GetTransformFunc(attributes.GVK(schema)).Return(func(obj interface{}) (interface{}, error) { return obj, nil })
|
||||
bloi.EXPECT().ListByOptions(req.Context(), opts, partitions, req.Namespace).Return(listToReturn, len(listToReturn.Items), "", nil)
|
||||
list, total, contToken, err := s.ListByPartitions(req, schema, partitions)
|
||||
assert.Nil(t, err)
|
||||
@@ -253,11 +256,13 @@ func TestListByPartitions(t *testing.T) {
|
||||
nsi := NewMockCache(gomock.NewController(t))
|
||||
cg := NewMockClientGetter(gomock.NewController(t))
|
||||
cf := NewMockCacheFactory(gomock.NewController(t))
|
||||
tb := NewMockTransformBuilder(gomock.NewController(t))
|
||||
|
||||
s := &Store{
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
transformBuilder: tb,
|
||||
}
|
||||
var partitions []partition.Partition
|
||||
req := &types.APIRequest{
|
||||
@@ -317,11 +322,13 @@ func TestListByPartitions(t *testing.T) {
|
||||
nsi := NewMockCache(gomock.NewController(t))
|
||||
cg := NewMockClientGetter(gomock.NewController(t))
|
||||
cf := NewMockCacheFactory(gomock.NewController(t))
|
||||
tb := NewMockTransformBuilder(gomock.NewController(t))
|
||||
|
||||
s := &Store{
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
transformBuilder: tb,
|
||||
}
|
||||
var partitions []partition.Partition
|
||||
req := &types.APIRequest{
|
||||
@@ -380,11 +387,13 @@ func TestListByPartitions(t *testing.T) {
|
||||
cg := NewMockClientGetter(gomock.NewController(t))
|
||||
cf := NewMockCacheFactory(gomock.NewController(t))
|
||||
ri := NewMockResourceInterface(gomock.NewController(t))
|
||||
tb := NewMockTransformBuilder(gomock.NewController(t))
|
||||
|
||||
s := &Store{
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
transformBuilder: tb,
|
||||
}
|
||||
var partitions []partition.Partition
|
||||
req := &types.APIRequest{
|
||||
@@ -432,7 +441,8 @@ func TestListByPartitions(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
cg.EXPECT().TableAdminClient(req, schema, "", &WarningBuffer{}).Return(ri, nil)
|
||||
// This tests that fields are being extracted from schema columns and the type specific fields map
|
||||
cf.EXPECT().CacheFor([][]string{{"some", "field"}, {"gvk", "specific", "fields"}}, &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(schema), attributes.Namespaced(schema)).Return(factory.Cache{}, fmt.Errorf("error"))
|
||||
tb.EXPECT().GetTransformFunc(attributes.GVK(schema)).Return(func(obj interface{}) (interface{}, error) { return obj, nil })
|
||||
cf.EXPECT().CacheFor([][]string{{"some", "field"}, {`id`}, {`metadata`, `state`, `name`}, {"gvk", "specific", "fields"}}, gomock.Any(), &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(schema), attributes.Namespaced(schema)).Return(factory.Cache{}, fmt.Errorf("error"))
|
||||
|
||||
_, _, _, err = s.ListByPartitions(req, schema, partitions)
|
||||
assert.NotNil(t, err)
|
||||
@@ -447,6 +457,7 @@ func TestListByPartitions(t *testing.T) {
|
||||
cf := NewMockCacheFactory(gomock.NewController(t))
|
||||
ri := NewMockResourceInterface(gomock.NewController(t))
|
||||
bloi := NewMockByOptionsLister(gomock.NewController(t))
|
||||
tb := NewMockTransformBuilder(gomock.NewController(t))
|
||||
inf := &informer.Informer{
|
||||
ByOptionsLister: bloi,
|
||||
}
|
||||
@@ -454,9 +465,10 @@ func TestListByPartitions(t *testing.T) {
|
||||
ByOptionsLister: inf,
|
||||
}
|
||||
s := &Store{
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
transformBuilder: tb,
|
||||
}
|
||||
var partitions []partition.Partition
|
||||
req := &types.APIRequest{
|
||||
@@ -504,8 +516,9 @@ func TestListByPartitions(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
cg.EXPECT().TableAdminClient(req, schema, "", &WarningBuffer{}).Return(ri, nil)
|
||||
// This tests that fields are being extracted from schema columns and the type specific fields map
|
||||
cf.EXPECT().CacheFor([][]string{{"some", "field"}, {"gvk", "specific", "fields"}}, &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(schema), attributes.Namespaced(schema)).Return(c, nil)
|
||||
cf.EXPECT().CacheFor([][]string{{"some", "field"}, {`id`}, {`metadata`, `state`, `name`}, {"gvk", "specific", "fields"}}, gomock.Any(), &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(schema), attributes.Namespaced(schema)).Return(c, nil)
|
||||
bloi.EXPECT().ListByOptions(req.Context(), opts, partitions, req.Namespace).Return(nil, 0, "", fmt.Errorf("error"))
|
||||
tb.EXPECT().GetTransformFunc(attributes.GVK(schema)).Return(func(obj interface{}) (interface{}, error) { return obj, nil })
|
||||
|
||||
_, _, _, err = s.ListByPartitions(req, schema, partitions)
|
||||
assert.NotNil(t, err)
|
||||
@@ -531,19 +544,22 @@ func TestReset(t *testing.T) {
|
||||
cf := NewMockCacheFactory(gomock.NewController(t))
|
||||
cs := NewMockSchemaColumnSetter(gomock.NewController(t))
|
||||
ri := NewMockResourceInterface(gomock.NewController(t))
|
||||
tb := NewMockTransformBuilder(gomock.NewController(t))
|
||||
nsc2 := factory.Cache{}
|
||||
s := &Store{
|
||||
namespaceCache: nsc,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
columnSetter: cs,
|
||||
cfInitializer: func() (CacheFactory, error) { return cf, nil },
|
||||
namespaceCache: nsc,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
columnSetter: cs,
|
||||
cfInitializer: func() (CacheFactory, error) { return cf, nil },
|
||||
transformBuilder: tb,
|
||||
}
|
||||
nsSchema := baseNSSchema
|
||||
cf.EXPECT().Reset().Return(nil)
|
||||
cs.EXPECT().SetColumns(gomock.Any(), gomock.Any()).Return(nil)
|
||||
cg.EXPECT().TableAdminClient(nil, &nsSchema, "", &WarningBuffer{}).Return(ri, nil)
|
||||
cf.EXPECT().CacheFor([][]string{{"metadata", "labels[field.cattle.io/projectId]"}}, &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(&nsSchema), false).Return(nsc2, nil)
|
||||
cf.EXPECT().CacheFor([][]string{{`id`}, {`metadata`, `state`, `name`}, {"metadata", "labels[field.cattle.io/projectId]"}}, gomock.Any(), &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(&nsSchema), false).Return(nsc2, nil)
|
||||
tb.EXPECT().GetTransformFunc(attributes.GVK(&nsSchema)).Return(func(obj interface{}) (interface{}, error) { return obj, nil })
|
||||
err := s.Reset()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, nsc2, s.namespaceCache)
|
||||
@@ -556,13 +572,15 @@ func TestReset(t *testing.T) {
|
||||
cg := NewMockClientGetter(gomock.NewController(t))
|
||||
cf := NewMockCacheFactory(gomock.NewController(t))
|
||||
cs := NewMockSchemaColumnSetter(gomock.NewController(t))
|
||||
tb := NewMockTransformBuilder(gomock.NewController(t))
|
||||
|
||||
s := &Store{
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
columnSetter: cs,
|
||||
cfInitializer: func() (CacheFactory, error) { return cf, nil },
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
columnSetter: cs,
|
||||
cfInitializer: func() (CacheFactory, error) { return cf, nil },
|
||||
transformBuilder: tb,
|
||||
}
|
||||
|
||||
cf.EXPECT().Reset().Return(fmt.Errorf("error"))
|
||||
@@ -577,13 +595,15 @@ func TestReset(t *testing.T) {
|
||||
cg := NewMockClientGetter(gomock.NewController(t))
|
||||
cf := NewMockCacheFactory(gomock.NewController(t))
|
||||
cs := NewMockSchemaColumnSetter(gomock.NewController(t))
|
||||
tb := NewMockTransformBuilder(gomock.NewController(t))
|
||||
|
||||
s := &Store{
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
columnSetter: cs,
|
||||
cfInitializer: func() (CacheFactory, error) { return cf, nil },
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
columnSetter: cs,
|
||||
cfInitializer: func() (CacheFactory, error) { return cf, nil },
|
||||
transformBuilder: tb,
|
||||
}
|
||||
|
||||
cf.EXPECT().Reset().Return(nil)
|
||||
@@ -599,13 +619,15 @@ func TestReset(t *testing.T) {
|
||||
cg := NewMockClientGetter(gomock.NewController(t))
|
||||
cf := NewMockCacheFactory(gomock.NewController(t))
|
||||
cs := NewMockSchemaColumnSetter(gomock.NewController(t))
|
||||
tb := NewMockTransformBuilder(gomock.NewController(t))
|
||||
|
||||
s := &Store{
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
columnSetter: cs,
|
||||
cfInitializer: func() (CacheFactory, error) { return cf, nil },
|
||||
namespaceCache: nsi,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
columnSetter: cs,
|
||||
cfInitializer: func() (CacheFactory, error) { return cf, nil },
|
||||
transformBuilder: tb,
|
||||
}
|
||||
nsSchema := baseNSSchema
|
||||
|
||||
@@ -624,20 +646,23 @@ func TestReset(t *testing.T) {
|
||||
cf := NewMockCacheFactory(gomock.NewController(t))
|
||||
cs := NewMockSchemaColumnSetter(gomock.NewController(t))
|
||||
ri := NewMockResourceInterface(gomock.NewController(t))
|
||||
tb := NewMockTransformBuilder(gomock.NewController(t))
|
||||
|
||||
s := &Store{
|
||||
namespaceCache: nsc,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
columnSetter: cs,
|
||||
cfInitializer: func() (CacheFactory, error) { return cf, nil },
|
||||
namespaceCache: nsc,
|
||||
clientGetter: cg,
|
||||
cacheFactory: cf,
|
||||
columnSetter: cs,
|
||||
cfInitializer: func() (CacheFactory, error) { return cf, nil },
|
||||
transformBuilder: tb,
|
||||
}
|
||||
nsSchema := baseNSSchema
|
||||
|
||||
cf.EXPECT().Reset().Return(nil)
|
||||
cs.EXPECT().SetColumns(gomock.Any(), gomock.Any()).Return(nil)
|
||||
cg.EXPECT().TableAdminClient(nil, &nsSchema, "", &WarningBuffer{}).Return(ri, nil)
|
||||
cf.EXPECT().CacheFor([][]string{{"metadata", "labels[field.cattle.io/projectId]"}}, &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(&nsSchema), false).Return(factory.Cache{}, fmt.Errorf("error"))
|
||||
cf.EXPECT().CacheFor([][]string{{`id`}, {`metadata`, `state`, `name`}, {"metadata", "labels[field.cattle.io/projectId]"}}, gomock.Any(), &tablelistconvert.Client{ResourceInterface: ri}, attributes.GVK(&nsSchema), false).Return(factory.Cache{}, fmt.Errorf("error"))
|
||||
tb.EXPECT().GetTransformFunc(attributes.GVK(&nsSchema)).Return(func(obj interface{}) (interface{}, error) { return obj, nil })
|
||||
err := s.Reset()
|
||||
assert.NotNil(t, err)
|
||||
},
|
||||
|
Reference in New Issue
Block a user