mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Merge pull request #79793 from wojtek-t/index_in_cacher
Simplify trigger functions in cacher
This commit is contained in:
commit
a930b5ca7e
@ -44,6 +44,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apiserver/pkg/storage:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/registry/generic"
|
"k8s.io/apiserver/pkg/registry/generic"
|
||||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
|
"k8s.io/apiserver/pkg/storage"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/client"
|
"k8s.io/kubernetes/pkg/kubelet/client"
|
||||||
@ -89,7 +90,11 @@ func NewStorage(optsGetter generic.RESTOptionsGetter, kubeletClientConfig client
|
|||||||
|
|
||||||
TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
|
TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
|
||||||
}
|
}
|
||||||
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: node.GetAttrs, TriggerFunc: node.NodeNameTriggerFunc}
|
options := &generic.StoreOptions{
|
||||||
|
RESTOptions: optsGetter,
|
||||||
|
AttrFunc: node.GetAttrs,
|
||||||
|
TriggerFunc: map[string]storage.TriggerPublisherFunc{"metadata.name": node.NodeNameTriggerFunc},
|
||||||
|
}
|
||||||
if err := store.CompleteWithOptions(options); err != nil {
|
if err := store.CompleteWithOptions(options); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -225,10 +225,8 @@ func MatchNode(label labels.Selector, field fields.Selector) pkgstorage.Selectio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NodeNameTriggerFunc(obj runtime.Object) []pkgstorage.MatchValue {
|
func NodeNameTriggerFunc(obj runtime.Object) string {
|
||||||
node := obj.(*api.Node)
|
return obj.(*api.Node).ObjectMeta.Name
|
||||||
result := pkgstorage.MatchValue{IndexName: "metadata.name", Value: node.ObjectMeta.Name}
|
|
||||||
return []pkgstorage.MatchValue{result}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResourceLocation returns a URL and transport which one can use to send traffic for the specified node.
|
// ResourceLocation returns a URL and transport which one can use to send traffic for the specified node.
|
||||||
|
@ -78,7 +78,11 @@ func NewStorage(optsGetter generic.RESTOptionsGetter, k client.ConnectionInfoGet
|
|||||||
|
|
||||||
TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
|
TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
|
||||||
}
|
}
|
||||||
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: pod.GetAttrs, TriggerFunc: pod.NodeNameTriggerFunc}
|
options := &generic.StoreOptions{
|
||||||
|
RESTOptions: optsGetter,
|
||||||
|
AttrFunc: pod.GetAttrs,
|
||||||
|
TriggerFunc: map[string]storage.TriggerPublisherFunc{"spec.nodeName": pod.NodeNameTriggerFunc},
|
||||||
|
}
|
||||||
if err := store.CompleteWithOptions(options); err != nil {
|
if err := store.CompleteWithOptions(options); err != nil {
|
||||||
panic(err) // TODO: Propagate error up
|
panic(err) // TODO: Propagate error up
|
||||||
}
|
}
|
||||||
|
@ -193,10 +193,8 @@ func MatchPod(label labels.Selector, field fields.Selector) storage.SelectionPre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NodeNameTriggerFunc(obj runtime.Object) []storage.MatchValue {
|
func NodeNameTriggerFunc(obj runtime.Object) string {
|
||||||
pod := obj.(*api.Pod)
|
return obj.(*api.Pod).Spec.NodeName
|
||||||
result := storage.MatchValue{IndexName: "spec.nodeName", Value: pod.Spec.NodeName}
|
|
||||||
return []storage.MatchValue{result}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodToSelectableFields returns a field set that represents the object
|
// PodToSelectableFields returns a field set that represents the object
|
||||||
|
@ -36,6 +36,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apiserver/pkg/storage:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apiserver/pkg/registry/generic"
|
"k8s.io/apiserver/pkg/registry/generic"
|
||||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
||||||
|
"k8s.io/apiserver/pkg/storage"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
"k8s.io/kubernetes/pkg/printers"
|
"k8s.io/kubernetes/pkg/printers"
|
||||||
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
|
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
|
||||||
@ -46,7 +47,11 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
|
|||||||
|
|
||||||
TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
|
TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
|
||||||
}
|
}
|
||||||
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: secret.GetAttrs, TriggerFunc: secret.SecretNameTriggerFunc}
|
options := &generic.StoreOptions{
|
||||||
|
RESTOptions: optsGetter,
|
||||||
|
AttrFunc: secret.GetAttrs,
|
||||||
|
TriggerFunc: map[string]storage.TriggerPublisherFunc{"metadata.name": secret.SecretNameTriggerFunc},
|
||||||
|
}
|
||||||
if err := store.CompleteWithOptions(options); err != nil {
|
if err := store.CompleteWithOptions(options); err != nil {
|
||||||
panic(err) // TODO: Propagate error up
|
panic(err) // TODO: Propagate error up
|
||||||
}
|
}
|
||||||
|
@ -116,10 +116,8 @@ func Matcher(label labels.Selector, field fields.Selector) pkgstorage.SelectionP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SecretNameTriggerFunc(obj runtime.Object) []pkgstorage.MatchValue {
|
func SecretNameTriggerFunc(obj runtime.Object) string {
|
||||||
secret := obj.(*api.Secret)
|
return obj.(*api.Secret).ObjectMeta.Name
|
||||||
result := pkgstorage.MatchValue{IndexName: "metadata.name", Value: secret.ObjectMeta.Name}
|
|
||||||
return []pkgstorage.MatchValue{result}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectableFields returns a field set that can be used for filter selection
|
// SelectableFields returns a field set that can be used for filter selection
|
||||||
|
@ -47,6 +47,6 @@ type RESTOptionsGetter interface {
|
|||||||
// StoreOptions is set of configuration options used to complete generic registries.
|
// StoreOptions is set of configuration options used to complete generic registries.
|
||||||
type StoreOptions struct {
|
type StoreOptions struct {
|
||||||
RESTOptions RESTOptionsGetter
|
RESTOptions RESTOptionsGetter
|
||||||
TriggerFunc storage.TriggerPublisherFunc
|
TriggerFunc storage.TriggerPublisherFuncs
|
||||||
AttrFunc storage.AttrFunc
|
AttrFunc storage.AttrFunc
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func StorageWithCacher(capacity int) generic.StorageDecorator {
|
|||||||
newFunc func() runtime.Object,
|
newFunc func() runtime.Object,
|
||||||
newListFunc func() runtime.Object,
|
newListFunc func() runtime.Object,
|
||||||
getAttrsFunc storage.AttrFunc,
|
getAttrsFunc storage.AttrFunc,
|
||||||
triggerFunc storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc, error) {
|
triggerFuncs storage.TriggerPublisherFuncs) (storage.Interface, factory.DestroyFunc, error) {
|
||||||
|
|
||||||
s, d, err := generic.NewRawStorage(storageConfig)
|
s, d, err := generic.NewRawStorage(storageConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -56,16 +56,16 @@ func StorageWithCacher(capacity int) generic.StorageDecorator {
|
|||||||
// TODO: we would change this later to make storage always have cacher and hide low level KV layer inside.
|
// TODO: we would change this later to make storage always have cacher and hide low level KV layer inside.
|
||||||
// Currently it has two layers of same storage interface -- cacher and low level kv.
|
// Currently it has two layers of same storage interface -- cacher and low level kv.
|
||||||
cacherConfig := cacherstorage.Config{
|
cacherConfig := cacherstorage.Config{
|
||||||
CacheCapacity: capacity,
|
CacheCapacity: capacity,
|
||||||
Storage: s,
|
Storage: s,
|
||||||
Versioner: etcd3.APIObjectVersioner{},
|
Versioner: etcd3.APIObjectVersioner{},
|
||||||
ResourcePrefix: resourcePrefix,
|
ResourcePrefix: resourcePrefix,
|
||||||
KeyFunc: keyFunc,
|
KeyFunc: keyFunc,
|
||||||
NewFunc: newFunc,
|
NewFunc: newFunc,
|
||||||
NewListFunc: newListFunc,
|
NewListFunc: newListFunc,
|
||||||
GetAttrsFunc: getAttrsFunc,
|
GetAttrsFunc: getAttrsFunc,
|
||||||
TriggerPublisherFunc: triggerFunc,
|
TriggerPublisherFuncs: triggerFuncs,
|
||||||
Codec: storageConfig.Codec,
|
Codec: storageConfig.Codec,
|
||||||
}
|
}
|
||||||
cacher, err := cacherstorage.NewCacherFromConfig(cacherConfig)
|
cacher, err := cacherstorage.NewCacherFromConfig(cacherConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1287,11 +1287,6 @@ func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error {
|
|||||||
return e.KeyFunc(genericapirequest.NewContext(), accessor.GetName())
|
return e.KeyFunc(genericapirequest.NewContext(), accessor.GetName())
|
||||||
}
|
}
|
||||||
|
|
||||||
triggerFunc := options.TriggerFunc
|
|
||||||
if triggerFunc == nil {
|
|
||||||
triggerFunc = storage.NoTriggerPublisher
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.DeleteCollectionWorkers == 0 {
|
if e.DeleteCollectionWorkers == 0 {
|
||||||
e.DeleteCollectionWorkers = opts.DeleteCollectionWorkers
|
e.DeleteCollectionWorkers = opts.DeleteCollectionWorkers
|
||||||
}
|
}
|
||||||
@ -1318,7 +1313,7 @@ func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error {
|
|||||||
e.NewFunc,
|
e.NewFunc,
|
||||||
e.NewListFunc,
|
e.NewListFunc,
|
||||||
attrFunc,
|
attrFunc,
|
||||||
triggerFunc,
|
options.TriggerFunc,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -32,7 +32,7 @@ type StorageDecorator func(
|
|||||||
newFunc func() runtime.Object,
|
newFunc func() runtime.Object,
|
||||||
newListFunc func() runtime.Object,
|
newListFunc func() runtime.Object,
|
||||||
getAttrsFunc storage.AttrFunc,
|
getAttrsFunc storage.AttrFunc,
|
||||||
trigger storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc, error)
|
trigger storage.TriggerPublisherFuncs) (storage.Interface, factory.DestroyFunc, error)
|
||||||
|
|
||||||
// UndecoratedStorage returns the given a new storage from the given config
|
// UndecoratedStorage returns the given a new storage from the given config
|
||||||
// without any decoration.
|
// without any decoration.
|
||||||
@ -43,7 +43,7 @@ func UndecoratedStorage(
|
|||||||
newFunc func() runtime.Object,
|
newFunc func() runtime.Object,
|
||||||
newListFunc func() runtime.Object,
|
newListFunc func() runtime.Object,
|
||||||
getAttrsFunc storage.AttrFunc,
|
getAttrsFunc storage.AttrFunc,
|
||||||
trigger storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc, error) {
|
trigger storage.TriggerPublisherFuncs) (storage.Interface, factory.DestroyFunc, error) {
|
||||||
return NewRawStorage(config)
|
return NewRawStorage(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,9 +88,9 @@ type Config struct {
|
|||||||
// GetAttrsFunc is used to get object labels, fields
|
// GetAttrsFunc is used to get object labels, fields
|
||||||
GetAttrsFunc func(runtime.Object) (label labels.Set, field fields.Set, err error)
|
GetAttrsFunc func(runtime.Object) (label labels.Set, field fields.Set, err error)
|
||||||
|
|
||||||
// TriggerPublisherFunc is used for optimizing amount of watchers that
|
// TriggerPublisherFuncs is used for optimizing amount of watchers that
|
||||||
// needs to process an incoming event.
|
// needs to process an incoming event.
|
||||||
TriggerPublisherFunc storage.TriggerPublisherFunc
|
TriggerPublisherFuncs storage.TriggerPublisherFuncs
|
||||||
|
|
||||||
// NewFunc is a function that creates new empty object storing a object of type Type.
|
// NewFunc is a function that creates new empty object storing a object of type Type.
|
||||||
NewFunc func() runtime.Object
|
NewFunc func() runtime.Object
|
||||||
@ -209,6 +209,11 @@ func (t *watcherBookmarkTimeBuckets) popExpiredWatchers() [][]*cacheWatcher {
|
|||||||
|
|
||||||
type filterWithAttrsFunc func(key string, l labels.Set, f fields.Set) bool
|
type filterWithAttrsFunc func(key string, l labels.Set, f fields.Set) bool
|
||||||
|
|
||||||
|
type indexedTriggerFunc struct {
|
||||||
|
indexName string
|
||||||
|
triggerFunc storage.TriggerPublisherFunc
|
||||||
|
}
|
||||||
|
|
||||||
// Cacher is responsible for serving WATCH and LIST requests for a given
|
// Cacher is responsible for serving WATCH and LIST requests for a given
|
||||||
// resource from its internal cache and updating its cache in the background
|
// resource from its internal cache and updating its cache in the background
|
||||||
// based on the underlying storage contents.
|
// based on the underlying storage contents.
|
||||||
@ -248,9 +253,9 @@ type Cacher struct {
|
|||||||
// newFunc is a function that creates new empty object storing a object of type Type.
|
// newFunc is a function that creates new empty object storing a object of type Type.
|
||||||
newFunc func() runtime.Object
|
newFunc func() runtime.Object
|
||||||
|
|
||||||
// triggerFunc is used for optimizing amount of watchers that needs to process
|
// indexedTrigger is used for optimizing amount of watchers that needs to process
|
||||||
// an incoming event.
|
// an incoming event.
|
||||||
triggerFunc storage.TriggerPublisherFunc
|
indexedTrigger *indexedTriggerFunc
|
||||||
// watchers is mapping from the value of trigger function that a
|
// watchers is mapping from the value of trigger function that a
|
||||||
// watcher is interested into the watchers
|
// watcher is interested into the watchers
|
||||||
watcherIdx int
|
watcherIdx int
|
||||||
@ -300,15 +305,32 @@ func NewCacherFromConfig(config Config) (*Cacher, error) {
|
|||||||
return nil, fmt.Errorf("storage codec doesn't seem to match given type: %v", err)
|
return nil, fmt.Errorf("storage codec doesn't seem to match given type: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var indexedTrigger *indexedTriggerFunc
|
||||||
|
if config.TriggerPublisherFuncs != nil {
|
||||||
|
// For now, we don't support multiple trigger functions defined
|
||||||
|
// for a given resource.
|
||||||
|
if len(config.TriggerPublisherFuncs) > 1 {
|
||||||
|
return nil, fmt.Errorf("cacher %s doesn't support more than one TriggerPublisherFunc: ", reflect.TypeOf(obj).String())
|
||||||
|
}
|
||||||
|
for key, value := range config.TriggerPublisherFuncs {
|
||||||
|
if value != nil {
|
||||||
|
indexedTrigger = &indexedTriggerFunc{
|
||||||
|
indexName: key,
|
||||||
|
triggerFunc: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clock := clock.RealClock{}
|
clock := clock.RealClock{}
|
||||||
cacher := &Cacher{
|
cacher := &Cacher{
|
||||||
ready: newReady(),
|
ready: newReady(),
|
||||||
storage: config.Storage,
|
storage: config.Storage,
|
||||||
objectType: reflect.TypeOf(obj),
|
objectType: reflect.TypeOf(obj),
|
||||||
versioner: config.Versioner,
|
versioner: config.Versioner,
|
||||||
newFunc: config.NewFunc,
|
newFunc: config.NewFunc,
|
||||||
triggerFunc: config.TriggerPublisherFunc,
|
indexedTrigger: indexedTrigger,
|
||||||
watcherIdx: 0,
|
watcherIdx: 0,
|
||||||
watchers: indexedWatchers{
|
watchers: indexedWatchers{
|
||||||
allWatchers: make(map[int]*cacheWatcher),
|
allWatchers: make(map[int]*cacheWatcher),
|
||||||
valueWatchers: make(map[string]watchersMap),
|
valueWatchers: make(map[string]watchersMap),
|
||||||
@ -419,23 +441,27 @@ func (c *Cacher) Watch(ctx context.Context, key string, resourceVersion string,
|
|||||||
c.ready.wait()
|
c.ready.wait()
|
||||||
|
|
||||||
triggerValue, triggerSupported := "", false
|
triggerValue, triggerSupported := "", false
|
||||||
// TODO: Currently we assume that in a given Cacher object, any <predicate> that is
|
if c.indexedTrigger != nil {
|
||||||
// passed here is aware of exactly the same trigger (at most one).
|
for _, field := range pred.IndexFields {
|
||||||
// Thus, either 0 or 1 values will be returned.
|
if field == c.indexedTrigger.indexName {
|
||||||
if matchValues := pred.MatcherIndex(); len(matchValues) > 0 {
|
if value, ok := pred.Field.RequiresExactMatch(field); ok {
|
||||||
triggerValue, triggerSupported = matchValues[0].Value, true
|
triggerValue, triggerSupported = value, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is triggerFunc defined, but triggerSupported is false,
|
// If there is indexedTrigger defined, but triggerSupported is false,
|
||||||
// we can't narrow the amount of events significantly at this point.
|
// we can't narrow the amount of events significantly at this point.
|
||||||
//
|
//
|
||||||
// That said, currently triggerFunc is defined only for Pods and Nodes,
|
// That said, currently indexedTrigger is defined only for couple resources:
|
||||||
// and there is only constant number of watchers for which triggerSupported
|
// Pods, Nodes, Secrets and ConfigMaps and there is only a constant
|
||||||
// is false (excluding those issues explicitly by users).
|
// number of watchers for which triggerSupported is false (excluding those
|
||||||
|
// issued explicitly by users).
|
||||||
// Thus, to reduce the risk of those watchers blocking all watchers of a
|
// Thus, to reduce the risk of those watchers blocking all watchers of a
|
||||||
// given resource in the system, we increase the sizes of buffers for them.
|
// given resource in the system, we increase the sizes of buffers for them.
|
||||||
chanSize := 10
|
chanSize := 10
|
||||||
if c.triggerFunc != nil && !triggerSupported {
|
if c.indexedTrigger != nil && !triggerSupported {
|
||||||
// TODO: We should tune this value and ideally make it dependent on the
|
// TODO: We should tune this value and ideally make it dependent on the
|
||||||
// number of objects of a given type and/or their churn.
|
// number of objects of a given type and/or their churn.
|
||||||
chanSize = 1000
|
chanSize = 1000
|
||||||
@ -711,29 +737,20 @@ func (c *Cacher) Count(pathPrefix string) (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cacher) triggerValues(event *watchCacheEvent) ([]string, bool) {
|
func (c *Cacher) triggerValues(event *watchCacheEvent) ([]string, bool) {
|
||||||
// TODO: Currently we assume that in a given Cacher object, its <c.triggerFunc>
|
if c.indexedTrigger == nil {
|
||||||
// is aware of exactly the same trigger (at most one). Thus calling:
|
|
||||||
// c.triggerFunc(<some object>)
|
|
||||||
// can return only 0 or 1 values.
|
|
||||||
// That means, that triggerValues itself may return up to 2 different values.
|
|
||||||
if c.triggerFunc == nil {
|
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make([]string, 0, 2)
|
result := make([]string, 0, 2)
|
||||||
matchValues := c.triggerFunc(event.Object)
|
result = append(result, c.indexedTrigger.triggerFunc(event.Object))
|
||||||
if len(matchValues) > 0 {
|
|
||||||
result = append(result, matchValues[0].Value)
|
|
||||||
}
|
|
||||||
if event.PrevObject == nil {
|
if event.PrevObject == nil {
|
||||||
return result, len(result) > 0
|
return result, true
|
||||||
}
|
}
|
||||||
prevMatchValues := c.triggerFunc(event.PrevObject)
|
prevTriggerValue := c.indexedTrigger.triggerFunc(event.PrevObject)
|
||||||
if len(prevMatchValues) > 0 {
|
if result[0] != prevTriggerValue {
|
||||||
if len(result) == 0 || result[0] != prevMatchValues[0].Value {
|
result = append(result, prevTriggerValue)
|
||||||
result = append(result, prevMatchValues[0].Value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result, len(result) > 0
|
return result, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cacher) processEvent(event *watchCacheEvent) {
|
func (c *Cacher) processEvent(event *watchCacheEvent) {
|
||||||
|
@ -73,16 +73,15 @@ type ResponseMeta struct {
|
|||||||
ResourceVersion uint64
|
ResourceVersion uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchValue defines a pair (<index name>, <value for that index>).
|
// TriggerPublisherFunc is a function that for a given object computes
|
||||||
type MatchValue struct {
|
// <value of an index> for a particular <index>.
|
||||||
IndexName string
|
// TODO(wojtek-t): Rename to IndexerFunc?
|
||||||
Value string
|
type TriggerPublisherFunc func(obj runtime.Object) string
|
||||||
}
|
|
||||||
|
|
||||||
// TriggerPublisherFunc is a function that takes an object, and returns a list of pairs
|
// TriggerPublisherFuncs is a mapping from <index name> to function that
|
||||||
// (<index name>, <index value for the given object>) for all indexes known
|
// for a given object computes <value for that index>.
|
||||||
// to that function.
|
// TODO(wojtek-t): Rename to IndexerFuncs?
|
||||||
type TriggerPublisherFunc func(obj runtime.Object) []MatchValue
|
type TriggerPublisherFuncs map[string]TriggerPublisherFunc
|
||||||
|
|
||||||
// Everything accepts all objects.
|
// Everything accepts all objects.
|
||||||
var Everything = SelectionPredicate{
|
var Everything = SelectionPredicate{
|
||||||
|
@ -124,20 +124,6 @@ func (s *SelectionPredicate) MatchesSingle() (string, bool) {
|
|||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
// For any index defined by IndexFields, if a matcher can match only (a subset)
|
|
||||||
// of objects that return <value> for a given index, a pair (<index name>, <value>)
|
|
||||||
// wil be returned.
|
|
||||||
// TODO: Consider supporting also labels.
|
|
||||||
func (s *SelectionPredicate) MatcherIndex() []MatchValue {
|
|
||||||
var result []MatchValue
|
|
||||||
for _, field := range s.IndexFields {
|
|
||||||
if value, ok := s.Field.RequiresExactMatch(field); ok {
|
|
||||||
result = append(result, MatchValue{IndexName: field, Value: value})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty returns true if the predicate performs no filtering.
|
// Empty returns true if the predicate performs no filtering.
|
||||||
func (s *SelectionPredicate) Empty() bool {
|
func (s *SelectionPredicate) Empty() bool {
|
||||||
return s.Label.Empty() && s.Field.Empty()
|
return s.Label.Empty() && s.Field.Empty()
|
||||||
|
@ -39,14 +39,6 @@ func EverythingFunc(runtime.Object) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func NoTriggerFunc() []MatchValue {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NoTriggerPublisher(runtime.Object) []MatchValue {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) {
|
func NamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) {
|
||||||
meta, err := meta.Accessor(obj)
|
meta, err := meta.Accessor(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user