4
vendor/k8s.io/apiserver/pkg/registry/generic/OWNERS
generated
vendored
4
vendor/k8s.io/apiserver/pkg/registry/generic/OWNERS
generated
vendored
@@ -11,20 +11,16 @@ reviewers:
|
||||
- caesarxuchao
|
||||
- mikedanese
|
||||
- liggitt
|
||||
- nikhiljindal
|
||||
- gmarek
|
||||
- davidopp
|
||||
- saad-ali
|
||||
- janetkuo
|
||||
- pwittrock
|
||||
- ncdc
|
||||
- eparis
|
||||
- piosz
|
||||
- dims
|
||||
- hongchaodeng
|
||||
- krousey
|
||||
- xiang90
|
||||
- resouer
|
||||
- mqliang
|
||||
- sdminonne
|
||||
- enj
|
||||
|
||||
27
vendor/k8s.io/apiserver/pkg/registry/generic/registry/decorated_watcher.go
generated
vendored
27
vendor/k8s.io/apiserver/pkg/registry/generic/registry/decorated_watcher.go
generated
vendored
@@ -18,20 +18,18 @@ package registry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
)
|
||||
|
||||
type decoratedWatcher struct {
|
||||
w watch.Interface
|
||||
decorator ObjectFunc
|
||||
decorator func(runtime.Object)
|
||||
cancel context.CancelFunc
|
||||
resultCh chan watch.Event
|
||||
}
|
||||
|
||||
func newDecoratedWatcher(w watch.Interface, decorator ObjectFunc) *decoratedWatcher {
|
||||
func newDecoratedWatcher(w watch.Interface, decorator func(runtime.Object)) *decoratedWatcher {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
d := &decoratedWatcher{
|
||||
w: w,
|
||||
@@ -56,11 +54,7 @@ func (d *decoratedWatcher) run(ctx context.Context) {
|
||||
}
|
||||
switch recv.Type {
|
||||
case watch.Added, watch.Modified, watch.Deleted, watch.Bookmark:
|
||||
err := d.decorator(recv.Object)
|
||||
if err != nil {
|
||||
send = makeStatusErrorEvent(err)
|
||||
break
|
||||
}
|
||||
d.decorator(recv.Object)
|
||||
send = recv
|
||||
case watch.Error:
|
||||
send = recv
|
||||
@@ -87,16 +81,3 @@ func (d *decoratedWatcher) Stop() {
|
||||
func (d *decoratedWatcher) ResultChan() <-chan watch.Event {
|
||||
return d.resultCh
|
||||
}
|
||||
|
||||
func makeStatusErrorEvent(err error) watch.Event {
|
||||
status := &metav1.Status{
|
||||
Status: metav1.StatusFailure,
|
||||
Message: err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
Reason: metav1.StatusReasonInternalError,
|
||||
}
|
||||
return watch.Event{
|
||||
Type: watch.Error,
|
||||
Object: status,
|
||||
}
|
||||
}
|
||||
|
||||
34
vendor/k8s.io/apiserver/pkg/registry/generic/registry/dryrun.go
generated
vendored
34
vendor/k8s.io/apiserver/pkg/registry/generic/registry/dryrun.go
generated
vendored
@@ -35,7 +35,7 @@ func (s *DryRunnableStorage) Versioner() storage.Versioner {
|
||||
|
||||
func (s *DryRunnableStorage) Create(ctx context.Context, key string, obj, out runtime.Object, ttl uint64, dryRun bool) error {
|
||||
if dryRun {
|
||||
if err := s.Storage.Get(ctx, key, "", out, false); err == nil {
|
||||
if err := s.Storage.Get(ctx, key, storage.GetOptions{}, out); err == nil {
|
||||
return storage.NewKeyExistsError(key, 0)
|
||||
}
|
||||
return s.copyInto(obj, out)
|
||||
@@ -43,9 +43,9 @@ func (s *DryRunnableStorage) Create(ctx context.Context, key string, obj, out ru
|
||||
return s.Storage.Create(ctx, key, obj, out, ttl)
|
||||
}
|
||||
|
||||
func (s *DryRunnableStorage) Delete(ctx context.Context, key string, out runtime.Object, preconditions *storage.Preconditions, deleteValidation storage.ValidateObjectFunc, dryRun bool) error {
|
||||
func (s *DryRunnableStorage) Delete(ctx context.Context, key string, out runtime.Object, preconditions *storage.Preconditions, deleteValidation storage.ValidateObjectFunc, dryRun bool, cachedExistingObject runtime.Object) error {
|
||||
if dryRun {
|
||||
if err := s.Storage.Get(ctx, key, "", out, false); err != nil {
|
||||
if err := s.Storage.Get(ctx, key, storage.GetOptions{}, out); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := preconditions.Check(key, out); err != nil {
|
||||
@@ -53,34 +53,34 @@ func (s *DryRunnableStorage) Delete(ctx context.Context, key string, out runtime
|
||||
}
|
||||
return deleteValidation(ctx, out)
|
||||
}
|
||||
return s.Storage.Delete(ctx, key, out, preconditions, deleteValidation)
|
||||
return s.Storage.Delete(ctx, key, out, preconditions, deleteValidation, cachedExistingObject)
|
||||
}
|
||||
|
||||
func (s *DryRunnableStorage) Watch(ctx context.Context, key string, resourceVersion string, p storage.SelectionPredicate) (watch.Interface, error) {
|
||||
return s.Storage.Watch(ctx, key, resourceVersion, p)
|
||||
func (s *DryRunnableStorage) Watch(ctx context.Context, key string, opts storage.ListOptions) (watch.Interface, error) {
|
||||
return s.Storage.Watch(ctx, key, opts)
|
||||
}
|
||||
|
||||
func (s *DryRunnableStorage) WatchList(ctx context.Context, key string, resourceVersion string, p storage.SelectionPredicate) (watch.Interface, error) {
|
||||
return s.Storage.WatchList(ctx, key, resourceVersion, p)
|
||||
func (s *DryRunnableStorage) WatchList(ctx context.Context, key string, opts storage.ListOptions) (watch.Interface, error) {
|
||||
return s.Storage.WatchList(ctx, key, opts)
|
||||
}
|
||||
|
||||
func (s *DryRunnableStorage) Get(ctx context.Context, key string, resourceVersion string, objPtr runtime.Object, ignoreNotFound bool) error {
|
||||
return s.Storage.Get(ctx, key, resourceVersion, objPtr, ignoreNotFound)
|
||||
func (s *DryRunnableStorage) Get(ctx context.Context, key string, opts storage.GetOptions, objPtr runtime.Object) error {
|
||||
return s.Storage.Get(ctx, key, opts, objPtr)
|
||||
}
|
||||
|
||||
func (s *DryRunnableStorage) GetToList(ctx context.Context, key string, resourceVersion string, p storage.SelectionPredicate, listObj runtime.Object) error {
|
||||
return s.Storage.GetToList(ctx, key, resourceVersion, p, listObj)
|
||||
func (s *DryRunnableStorage) GetToList(ctx context.Context, key string, opts storage.ListOptions, listObj runtime.Object) error {
|
||||
return s.Storage.GetToList(ctx, key, opts, listObj)
|
||||
}
|
||||
|
||||
func (s *DryRunnableStorage) List(ctx context.Context, key string, resourceVersion string, p storage.SelectionPredicate, listObj runtime.Object) error {
|
||||
return s.Storage.List(ctx, key, resourceVersion, p, listObj)
|
||||
func (s *DryRunnableStorage) List(ctx context.Context, key string, opts storage.ListOptions, listObj runtime.Object) error {
|
||||
return s.Storage.List(ctx, key, opts, listObj)
|
||||
}
|
||||
|
||||
func (s *DryRunnableStorage) GuaranteedUpdate(
|
||||
ctx context.Context, key string, ptrToType runtime.Object, ignoreNotFound bool,
|
||||
preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc, dryRun bool, suggestion ...runtime.Object) error {
|
||||
preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc, dryRun bool, cachedExistingObject runtime.Object) error {
|
||||
if dryRun {
|
||||
err := s.Storage.Get(ctx, key, "", ptrToType, ignoreNotFound)
|
||||
err := s.Storage.Get(ctx, key, storage.GetOptions{IgnoreNotFound: ignoreNotFound}, ptrToType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -98,7 +98,7 @@ func (s *DryRunnableStorage) GuaranteedUpdate(
|
||||
}
|
||||
return s.copyInto(out, ptrToType)
|
||||
}
|
||||
return s.Storage.GuaranteedUpdate(ctx, key, ptrToType, ignoreNotFound, preconditions, tryUpdate, suggestion...)
|
||||
return s.Storage.GuaranteedUpdate(ctx, key, ptrToType, ignoreNotFound, preconditions, tryUpdate, cachedExistingObject)
|
||||
}
|
||||
|
||||
func (s *DryRunnableStorage) Count(key string) (int64, error) {
|
||||
|
||||
30
vendor/k8s.io/apiserver/pkg/registry/generic/registry/storage_factory.go
generated
vendored
30
vendor/k8s.io/apiserver/pkg/registry/generic/registry/storage_factory.go
generated
vendored
@@ -17,10 +17,12 @@ limitations under the License.
|
||||
package registry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
"k8s.io/apiserver/pkg/storage"
|
||||
@@ -32,7 +34,7 @@ import (
|
||||
)
|
||||
|
||||
// Creates a cacher based given storageConfig.
|
||||
func StorageWithCacher(capacity int) generic.StorageDecorator {
|
||||
func StorageWithCacher() generic.StorageDecorator {
|
||||
return func(
|
||||
storageConfig *storagebackend.Config,
|
||||
resourcePrefix string,
|
||||
@@ -43,22 +45,15 @@ func StorageWithCacher(capacity int) generic.StorageDecorator {
|
||||
triggerFuncs storage.IndexerFuncs,
|
||||
indexers *cache.Indexers) (storage.Interface, factory.DestroyFunc, error) {
|
||||
|
||||
s, d, err := generic.NewRawStorage(storageConfig)
|
||||
s, d, err := generic.NewRawStorage(storageConfig, newFunc)
|
||||
if err != nil {
|
||||
return s, d, err
|
||||
}
|
||||
if capacity <= 0 {
|
||||
klog.V(5).Infof("Storage caching is disabled for %T", newFunc())
|
||||
return s, d, nil
|
||||
}
|
||||
if klog.V(5) {
|
||||
klog.Infof("Storage caching is enabled for %T with capacity %v", newFunc(), capacity)
|
||||
if klog.V(5).Enabled() {
|
||||
klog.Infof("Storage caching is enabled for %s", objectTypeToString(newFunc()))
|
||||
}
|
||||
|
||||
// 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.
|
||||
cacherConfig := cacherstorage.Config{
|
||||
CacheCapacity: capacity,
|
||||
Storage: s,
|
||||
Versioner: etcd3.APIObjectVersioner{},
|
||||
ResourcePrefix: resourcePrefix,
|
||||
@@ -88,6 +83,17 @@ func StorageWithCacher(capacity int) generic.StorageDecorator {
|
||||
}
|
||||
}
|
||||
|
||||
func objectTypeToString(obj runtime.Object) string {
|
||||
// special-case unstructured objects that tell us their apiVersion/kind
|
||||
if u, isUnstructured := obj.(*unstructured.Unstructured); isUnstructured {
|
||||
if apiVersion, kind := u.GetAPIVersion(), u.GetKind(); len(apiVersion) > 0 && len(kind) > 0 {
|
||||
return fmt.Sprintf("apiVersion=%s, kind=%s", apiVersion, kind)
|
||||
}
|
||||
}
|
||||
// otherwise just return the type
|
||||
return fmt.Sprintf("%T", obj)
|
||||
}
|
||||
|
||||
// TODO : Remove all the code below when PR
|
||||
// https://github.com/kubernetes/kubernetes/pull/50690
|
||||
// merges as that shuts down storage properly
|
||||
|
||||
326
vendor/k8s.io/apiserver/pkg/registry/generic/registry/store.go
generated
vendored
326
vendor/k8s.io/apiserver/pkg/registry/generic/registry/store.go
generated
vendored
@@ -19,7 +19,6 @@ package registry
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -46,27 +45,41 @@ import (
|
||||
"k8s.io/apiserver/pkg/storage/etcd3/metrics"
|
||||
"k8s.io/apiserver/pkg/util/dryrun"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// ObjectFunc is a function to act on a given object. An error may be returned
|
||||
// if the hook cannot be completed. An ObjectFunc may transform the provided
|
||||
// object.
|
||||
type ObjectFunc func(obj runtime.Object) error
|
||||
// FinishFunc is a function returned by Begin hooks to complete an operation.
|
||||
type FinishFunc func(ctx context.Context, success bool)
|
||||
|
||||
// AfterDeleteFunc is the type used for the Store.AfterDelete hook.
|
||||
type AfterDeleteFunc func(obj runtime.Object, options *metav1.DeleteOptions)
|
||||
|
||||
// BeginCreateFunc is the type used for the Store.BeginCreate hook.
|
||||
type BeginCreateFunc func(ctx context.Context, obj runtime.Object, options *metav1.CreateOptions) (FinishFunc, error)
|
||||
|
||||
// AfterCreateFunc is the type used for the Store.AfterCreate hook.
|
||||
type AfterCreateFunc func(obj runtime.Object, options *metav1.CreateOptions)
|
||||
|
||||
// BeginUpdateFunc is the type used for the Store.BeginUpdate hook.
|
||||
type BeginUpdateFunc func(ctx context.Context, obj, old runtime.Object, options *metav1.UpdateOptions) (FinishFunc, error)
|
||||
|
||||
// AfterUpdateFunc is the type used for the Store.AfterUpdate hook.
|
||||
type AfterUpdateFunc func(obj runtime.Object, options *metav1.UpdateOptions)
|
||||
|
||||
// GenericStore interface can be used for type assertions when we need to access the underlying strategies.
|
||||
type GenericStore interface {
|
||||
GetCreateStrategy() rest.RESTCreateStrategy
|
||||
GetUpdateStrategy() rest.RESTUpdateStrategy
|
||||
GetDeleteStrategy() rest.RESTDeleteStrategy
|
||||
GetExportStrategy() rest.RESTExportStrategy
|
||||
}
|
||||
|
||||
// Store implements pkg/api/rest.StandardStorage. It's intended to be
|
||||
// embeddable and allows the consumer to implement any non-generic functions
|
||||
// that are required. This object is intended to be copyable so that it can be
|
||||
// used in different ways but share the same underlying behavior.
|
||||
// Store implements k8s.io/apiserver/pkg/registry/rest.StandardStorage. It's
|
||||
// intended to be embeddable and allows the consumer to implement any
|
||||
// non-generic functions that are required. This object is intended to be
|
||||
// copyable so that it can be used in different ways but share the same
|
||||
// underlying behavior.
|
||||
//
|
||||
// All fields are required unless specified.
|
||||
//
|
||||
@@ -145,24 +158,37 @@ type Store struct {
|
||||
// integrations that are above storage and should only be used for
|
||||
// specific cases where storage of the value is not appropriate, since
|
||||
// they cannot be watched.
|
||||
Decorator ObjectFunc
|
||||
Decorator func(runtime.Object)
|
||||
|
||||
// CreateStrategy implements resource-specific behavior during creation.
|
||||
CreateStrategy rest.RESTCreateStrategy
|
||||
// BeginCreate is an optional hook that returns a "transaction-like"
|
||||
// commit/revert function which will be called at the end of the operation,
|
||||
// but before AfterCreate and Decorator, indicating via the argument
|
||||
// whether the operation succeeded. If this returns an error, the function
|
||||
// is not called. Almost nobody should use this hook.
|
||||
BeginCreate BeginCreateFunc
|
||||
// AfterCreate implements a further operation to run after a resource is
|
||||
// created and before it is decorated, optional.
|
||||
AfterCreate ObjectFunc
|
||||
AfterCreate AfterCreateFunc
|
||||
|
||||
// UpdateStrategy implements resource-specific behavior during updates.
|
||||
UpdateStrategy rest.RESTUpdateStrategy
|
||||
// BeginUpdate is an optional hook that returns a "transaction-like"
|
||||
// commit/revert function which will be called at the end of the operation,
|
||||
// but before AfterUpdate and Decorator, indicating via the argument
|
||||
// whether the operation succeeded. If this returns an error, the function
|
||||
// is not called. Almost nobody should use this hook.
|
||||
BeginUpdate BeginUpdateFunc
|
||||
// AfterUpdate implements a further operation to run after a resource is
|
||||
// updated and before it is decorated, optional.
|
||||
AfterUpdate ObjectFunc
|
||||
AfterUpdate AfterUpdateFunc
|
||||
|
||||
// DeleteStrategy implements resource-specific behavior during deletion.
|
||||
DeleteStrategy rest.RESTDeleteStrategy
|
||||
// AfterDelete implements a further operation to run after a resource is
|
||||
// deleted and before it is decorated, optional.
|
||||
AfterDelete ObjectFunc
|
||||
AfterDelete AfterDeleteFunc
|
||||
// ReturnDeletedObject determines whether the Store returns the object
|
||||
// that was deleted. Otherwise, return a generic success status response.
|
||||
ReturnDeletedObject bool
|
||||
@@ -171,13 +197,15 @@ type Store struct {
|
||||
// If specified, this is checked in addition to standard finalizer,
|
||||
// deletionTimestamp, and deletionGracePeriodSeconds checks.
|
||||
ShouldDeleteDuringUpdate func(ctx context.Context, key string, obj, existing runtime.Object) bool
|
||||
// ExportStrategy implements resource-specific behavior during export,
|
||||
// optional. Exported objects are not decorated.
|
||||
ExportStrategy rest.RESTExportStrategy
|
||||
|
||||
// TableConvertor is an optional interface for transforming items or lists
|
||||
// of items into tabular output. If unset, the default will be used.
|
||||
TableConvertor rest.TableConvertor
|
||||
|
||||
// ResetFieldsStrategy provides the fields reset by the strategy that
|
||||
// should not be modified by the user.
|
||||
ResetFieldsStrategy rest.ResetFieldsStrategy
|
||||
|
||||
// Storage is the interface for the underlying storage for the
|
||||
// resource. It is wrapped into a "DryRunnableStorage" that will
|
||||
// either pass-through or simply dry-run.
|
||||
@@ -194,7 +222,6 @@ type Store struct {
|
||||
|
||||
// Note: the rest.StandardStorage interface aggregates the common REST verbs
|
||||
var _ rest.StandardStorage = &Store{}
|
||||
var _ rest.Exporter = &Store{}
|
||||
var _ rest.TableConvertor = &Store{}
|
||||
var _ GenericStore = &Store{}
|
||||
|
||||
@@ -283,11 +310,6 @@ func (e *Store) GetDeleteStrategy() rest.RESTDeleteStrategy {
|
||||
return e.DeleteStrategy
|
||||
}
|
||||
|
||||
// GetExportStrategy implements GenericStore.
|
||||
func (e *Store) GetExportStrategy() rest.RESTExportStrategy {
|
||||
return e.ExportStrategy
|
||||
}
|
||||
|
||||
// List returns a list of items matching labels and field according to the
|
||||
// store's PredicateFunc.
|
||||
func (e *Store) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
|
||||
@@ -304,9 +326,7 @@ func (e *Store) List(ctx context.Context, options *metainternalversion.ListOptio
|
||||
return nil, err
|
||||
}
|
||||
if e.Decorator != nil {
|
||||
if err := e.Decorator(out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.Decorator(out)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
@@ -322,20 +342,37 @@ func (e *Store) ListPredicate(ctx context.Context, p storage.SelectionPredicate,
|
||||
p.Continue = options.Continue
|
||||
list := e.NewListFunc()
|
||||
qualifiedResource := e.qualifiedResourceFromContext(ctx)
|
||||
storageOpts := storage.ListOptions{ResourceVersion: options.ResourceVersion, ResourceVersionMatch: options.ResourceVersionMatch, Predicate: p}
|
||||
if name, ok := p.MatchesSingle(); ok {
|
||||
if key, err := e.KeyFunc(ctx, name); err == nil {
|
||||
err := e.Storage.GetToList(ctx, key, options.ResourceVersion, p, list)
|
||||
err := e.Storage.GetToList(ctx, key, storageOpts, list)
|
||||
return list, storeerr.InterpretListError(err, qualifiedResource)
|
||||
}
|
||||
// if we cannot extract a key based on the current context, the optimization is skipped
|
||||
}
|
||||
|
||||
err := e.Storage.List(ctx, e.KeyRootFunc(ctx), options.ResourceVersion, p, list)
|
||||
err := e.Storage.List(ctx, e.KeyRootFunc(ctx), storageOpts, list)
|
||||
return list, storeerr.InterpretListError(err, qualifiedResource)
|
||||
}
|
||||
|
||||
// finishNothing is a do-nothing FinishFunc.
|
||||
func finishNothing(context.Context, bool) {}
|
||||
|
||||
// Create inserts a new item according to the unique key from the object.
|
||||
func (e *Store) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
|
||||
var finishCreate FinishFunc = finishNothing
|
||||
|
||||
if e.BeginCreate != nil {
|
||||
fn, err := e.BeginCreate(ctx, obj, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finishCreate = fn
|
||||
defer func() {
|
||||
finishCreate(ctx, false)
|
||||
}()
|
||||
}
|
||||
|
||||
if err := rest.BeforeCreate(e.CreateStrategy, ctx, obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -367,7 +404,7 @@ func (e *Store) Create(ctx context.Context, obj runtime.Object, createValidation
|
||||
if !apierrors.IsAlreadyExists(err) {
|
||||
return nil, err
|
||||
}
|
||||
if errGet := e.Storage.Get(ctx, key, "", out, false); errGet != nil {
|
||||
if errGet := e.Storage.Get(ctx, key, storage.GetOptions{}, out); errGet != nil {
|
||||
return nil, err
|
||||
}
|
||||
accessor, errGetAcc := meta.Accessor(out)
|
||||
@@ -380,15 +417,17 @@ func (e *Store) Create(ctx context.Context, obj runtime.Object, createValidation
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
// The operation has succeeded. Call the finish function if there is one,
|
||||
// and then make sure the defer doesn't call it again.
|
||||
fn := finishCreate
|
||||
finishCreate = finishNothing
|
||||
fn(ctx, true)
|
||||
|
||||
if e.AfterCreate != nil {
|
||||
if err := e.AfterCreate(out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.AfterCreate(out, options)
|
||||
}
|
||||
if e.Decorator != nil {
|
||||
if err := e.Decorator(out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.Decorator(out)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
@@ -423,16 +462,16 @@ func ShouldDeleteDuringUpdate(ctx context.Context, key string, obj, existing run
|
||||
|
||||
// deleteWithoutFinalizers handles deleting an object ignoring its finalizer list.
|
||||
// Used for objects that are either been finalized or have never initialized.
|
||||
func (e *Store) deleteWithoutFinalizers(ctx context.Context, name, key string, obj runtime.Object, preconditions *storage.Preconditions, dryRun bool) (runtime.Object, bool, error) {
|
||||
func (e *Store) deleteWithoutFinalizers(ctx context.Context, name, key string, obj runtime.Object, preconditions *storage.Preconditions, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
|
||||
out := e.NewFunc()
|
||||
klog.V(6).Infof("going to delete %s from registry, triggered by update", name)
|
||||
// Using the rest.ValidateAllObjectFunc because the request is an UPDATE request and has already passed the admission for the UPDATE verb.
|
||||
if err := e.Storage.Delete(ctx, key, out, preconditions, rest.ValidateAllObjectFunc, dryRun); err != nil {
|
||||
if err := e.Storage.Delete(ctx, key, out, preconditions, rest.ValidateAllObjectFunc, dryrun.IsDryRun(options.DryRun), nil); err != nil {
|
||||
// Deletion is racy, i.e., there could be multiple update
|
||||
// requests to remove all finalizers from the object, so we
|
||||
// ignore the NotFound error.
|
||||
if storage.IsNotFound(err) {
|
||||
_, err := e.finalizeDelete(ctx, obj, true)
|
||||
_, err := e.finalizeDelete(ctx, obj, true, options)
|
||||
// clients are expecting an updated object if a PUT succeeded,
|
||||
// but finalizeDelete returns a metav1.Status, so return
|
||||
// the object in the request instead.
|
||||
@@ -440,7 +479,7 @@ func (e *Store) deleteWithoutFinalizers(ctx context.Context, name, key string, o
|
||||
}
|
||||
return nil, false, storeerr.InterpretDeleteError(err, e.qualifiedResourceFromContext(ctx), name)
|
||||
}
|
||||
_, err := e.finalizeDelete(ctx, out, true)
|
||||
_, err := e.finalizeDelete(ctx, out, true, options)
|
||||
// clients are expecting an updated object if a PUT succeeded, but
|
||||
// finalizeDelete returns a metav1.Status, so return the object in
|
||||
// the request instead.
|
||||
@@ -472,6 +511,16 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
|
||||
// deleteObj is only used in case a deletion is carried out
|
||||
var deleteObj runtime.Object
|
||||
err = e.Storage.GuaranteedUpdate(ctx, key, out, true, storagePreconditions, func(existing runtime.Object, res storage.ResponseMeta) (runtime.Object, *uint64, error) {
|
||||
existingResourceVersion, err := e.Storage.Versioner().ObjectResourceVersion(existing)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if existingResourceVersion == 0 {
|
||||
if !e.UpdateStrategy.AllowCreateOnUpdate() && !forceAllowCreate {
|
||||
return nil, nil, apierrors.NewNotFound(qualifiedResource, name)
|
||||
}
|
||||
}
|
||||
|
||||
// Given the existing object, get the new object
|
||||
obj, err := objInfo.UpdatedObject(ctx, existing)
|
||||
if err != nil {
|
||||
@@ -482,20 +531,26 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
|
||||
// the user does not have a resource version, then we populate it with
|
||||
// the latest version. Else, we check that the version specified by
|
||||
// the user matches the version of latest storage object.
|
||||
resourceVersion, err := e.Storage.Versioner().ObjectResourceVersion(obj)
|
||||
newResourceVersion, err := e.Storage.Versioner().ObjectResourceVersion(obj)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
doUnconditionalUpdate := resourceVersion == 0 && e.UpdateStrategy.AllowUnconditionalUpdate()
|
||||
doUnconditionalUpdate := newResourceVersion == 0 && e.UpdateStrategy.AllowUnconditionalUpdate()
|
||||
|
||||
version, err := e.Storage.Versioner().ObjectResourceVersion(existing)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if version == 0 {
|
||||
if !e.UpdateStrategy.AllowCreateOnUpdate() && !forceAllowCreate {
|
||||
return nil, nil, apierrors.NewNotFound(qualifiedResource, name)
|
||||
if existingResourceVersion == 0 {
|
||||
var finishCreate FinishFunc = finishNothing
|
||||
|
||||
if e.BeginCreate != nil {
|
||||
fn, err := e.BeginCreate(ctx, obj, newCreateOptionsFromUpdateOptions(options))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
finishCreate = fn
|
||||
defer func() {
|
||||
finishCreate(ctx, false)
|
||||
}()
|
||||
}
|
||||
|
||||
creating = true
|
||||
creatingObj = obj
|
||||
if err := rest.BeforeCreate(e.CreateStrategy, ctx, obj); err != nil {
|
||||
@@ -513,6 +568,12 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// The operation has succeeded. Call the finish function if there is one,
|
||||
// and then make sure the defer doesn't call it again.
|
||||
fn := finishCreate
|
||||
finishCreate = finishNothing
|
||||
fn(ctx, true)
|
||||
|
||||
return obj, &ttl, nil
|
||||
}
|
||||
|
||||
@@ -528,18 +589,32 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
|
||||
} else {
|
||||
// Check if the object's resource version matches the latest
|
||||
// resource version.
|
||||
if resourceVersion == 0 {
|
||||
if newResourceVersion == 0 {
|
||||
// TODO: The Invalid error should have a field for Resource.
|
||||
// After that field is added, we should fill the Resource and
|
||||
// leave the Kind field empty. See the discussion in #18526.
|
||||
qualifiedKind := schema.GroupKind{Group: qualifiedResource.Group, Kind: qualifiedResource.Resource}
|
||||
fieldErrList := field.ErrorList{field.Invalid(field.NewPath("metadata").Child("resourceVersion"), resourceVersion, "must be specified for an update")}
|
||||
fieldErrList := field.ErrorList{field.Invalid(field.NewPath("metadata").Child("resourceVersion"), newResourceVersion, "must be specified for an update")}
|
||||
return nil, nil, apierrors.NewInvalid(qualifiedKind, name, fieldErrList)
|
||||
}
|
||||
if resourceVersion != version {
|
||||
if newResourceVersion != existingResourceVersion {
|
||||
return nil, nil, apierrors.NewConflict(qualifiedResource, name, fmt.Errorf(OptimisticLockErrorMsg))
|
||||
}
|
||||
}
|
||||
|
||||
var finishUpdate FinishFunc = finishNothing
|
||||
|
||||
if e.BeginUpdate != nil {
|
||||
fn, err := e.BeginUpdate(ctx, obj, existing, options)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
finishUpdate = fn
|
||||
defer func() {
|
||||
finishUpdate(ctx, false)
|
||||
}()
|
||||
}
|
||||
|
||||
if err := rest.BeforeUpdate(e.UpdateStrategy, ctx, obj, existing); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -560,16 +635,23 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// The operation has succeeded. Call the finish function if there is one,
|
||||
// and then make sure the defer doesn't call it again.
|
||||
fn := finishUpdate
|
||||
finishUpdate = finishNothing
|
||||
fn(ctx, true)
|
||||
|
||||
if int64(ttl) != res.TTL {
|
||||
return obj, &ttl, nil
|
||||
}
|
||||
return obj, nil, nil
|
||||
}, dryrun.IsDryRun(options.DryRun))
|
||||
}, dryrun.IsDryRun(options.DryRun), nil)
|
||||
|
||||
if err != nil {
|
||||
// delete the object
|
||||
if err == errEmptiedFinalizers {
|
||||
return e.deleteWithoutFinalizers(ctx, name, key, deleteObj, storagePreconditions, dryrun.IsDryRun(options.DryRun))
|
||||
return e.deleteWithoutFinalizers(ctx, name, key, deleteObj, storagePreconditions, newDeleteOptionsFromUpdateOptions(options))
|
||||
}
|
||||
if creating {
|
||||
err = storeerr.InterpretCreateError(err, qualifiedResource, name)
|
||||
@@ -582,25 +664,40 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
|
||||
|
||||
if creating {
|
||||
if e.AfterCreate != nil {
|
||||
if err := e.AfterCreate(out); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
e.AfterCreate(out, newCreateOptionsFromUpdateOptions(options))
|
||||
}
|
||||
} else {
|
||||
if e.AfterUpdate != nil {
|
||||
if err := e.AfterUpdate(out); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
e.AfterUpdate(out, options)
|
||||
}
|
||||
}
|
||||
if e.Decorator != nil {
|
||||
if err := e.Decorator(out); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
e.Decorator(out)
|
||||
}
|
||||
return out, creating, nil
|
||||
}
|
||||
|
||||
// This is a helper to convert UpdateOptions to CreateOptions for the
|
||||
// create-on-update path.
|
||||
func newCreateOptionsFromUpdateOptions(in *metav1.UpdateOptions) *metav1.CreateOptions {
|
||||
co := &metav1.CreateOptions{
|
||||
DryRun: in.DryRun,
|
||||
FieldManager: in.FieldManager,
|
||||
}
|
||||
co.TypeMeta.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("CreateOptions"))
|
||||
return co
|
||||
}
|
||||
|
||||
// This is a helper to convert UpdateOptions to DeleteOptions for the
|
||||
// delete-on-update path.
|
||||
func newDeleteOptionsFromUpdateOptions(in *metav1.UpdateOptions) *metav1.DeleteOptions {
|
||||
do := &metav1.DeleteOptions{
|
||||
DryRun: in.DryRun,
|
||||
}
|
||||
do.TypeMeta.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("DeleteOptions"))
|
||||
return do
|
||||
}
|
||||
|
||||
// Get retrieves the item from storage.
|
||||
func (e *Store) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
|
||||
obj := e.NewFunc()
|
||||
@@ -608,13 +705,11 @@ func (e *Store) Get(ctx context.Context, name string, options *metav1.GetOptions
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := e.Storage.Get(ctx, key, options.ResourceVersion, obj, false); err != nil {
|
||||
if err := e.Storage.Get(ctx, key, storage.GetOptions{ResourceVersion: options.ResourceVersion}, obj); err != nil {
|
||||
return nil, storeerr.InterpretGetError(err, e.qualifiedResourceFromContext(ctx), name)
|
||||
}
|
||||
if e.Decorator != nil {
|
||||
if err := e.Decorator(obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.Decorator(obj)
|
||||
}
|
||||
return obj, nil
|
||||
}
|
||||
@@ -654,7 +749,9 @@ func shouldOrphanDependents(ctx context.Context, e *Store, accessor metav1.Objec
|
||||
}
|
||||
|
||||
// An explicit policy was set at deletion time, that overrides everything
|
||||
//lint:ignore SA1019 backwards compatibility
|
||||
if options != nil && options.OrphanDependents != nil {
|
||||
//lint:ignore SA1019 backwards compatibility
|
||||
return *options.OrphanDependents
|
||||
}
|
||||
if options != nil && options.PropagationPolicy != nil {
|
||||
@@ -679,10 +776,7 @@ func shouldOrphanDependents(ctx context.Context, e *Store, accessor metav1.Objec
|
||||
}
|
||||
|
||||
// Get default orphan policy from this REST object type if it exists
|
||||
if defaultGCPolicy == rest.OrphanDependents {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return defaultGCPolicy == rest.OrphanDependents
|
||||
}
|
||||
|
||||
// shouldDeleteDependents returns true if the finalizer for foreground deletion should be set
|
||||
@@ -698,6 +792,7 @@ func shouldDeleteDependents(ctx context.Context, e *Store, accessor metav1.Objec
|
||||
}
|
||||
|
||||
// If an explicit policy was set at deletion time, that overrides both
|
||||
//lint:ignore SA1019 backwards compatibility
|
||||
if options != nil && options.OrphanDependents != nil {
|
||||
return false
|
||||
}
|
||||
@@ -854,6 +949,7 @@ func (e *Store) updateForGracefulDeletionAndFinalizers(ctx context.Context, name
|
||||
return existing, nil
|
||||
}),
|
||||
dryrun.IsDryRun(options.DryRun),
|
||||
nil,
|
||||
)
|
||||
switch err {
|
||||
case nil:
|
||||
@@ -877,7 +973,7 @@ func (e *Store) updateForGracefulDeletionAndFinalizers(ctx context.Context, name
|
||||
// we should fall through and truly delete the object.
|
||||
return nil, false, true, out, lastExisting
|
||||
case errAlreadyDeleting:
|
||||
out, err = e.finalizeDelete(ctx, in, true)
|
||||
out, err = e.finalizeDelete(ctx, in, true, options)
|
||||
return err, false, false, out, lastExisting
|
||||
default:
|
||||
return storeerr.InterpretUpdateError(err, e.qualifiedResourceFromContext(ctx), name), false, false, out, lastExisting
|
||||
@@ -892,7 +988,7 @@ func (e *Store) Delete(ctx context.Context, name string, deleteValidation rest.V
|
||||
}
|
||||
obj := e.NewFunc()
|
||||
qualifiedResource := e.qualifiedResourceFromContext(ctx)
|
||||
if err = e.Storage.Get(ctx, key, "", obj, false); err != nil {
|
||||
if err = e.Storage.Get(ctx, key, storage.GetOptions{}, obj); err != nil {
|
||||
return nil, false, storeerr.InterpretDeleteError(err, qualifiedResource, name)
|
||||
}
|
||||
|
||||
@@ -911,7 +1007,7 @@ func (e *Store) Delete(ctx context.Context, name string, deleteValidation rest.V
|
||||
}
|
||||
// this means finalizers cannot be updated via DeleteOptions if a deletion is already pending
|
||||
if pendingGraceful {
|
||||
out, err := e.finalizeDelete(ctx, obj, false)
|
||||
out, err := e.finalizeDelete(ctx, obj, false, options)
|
||||
return out, false, err
|
||||
}
|
||||
// check if obj has pending finalizers
|
||||
@@ -961,18 +1057,18 @@ func (e *Store) Delete(ctx context.Context, name string, deleteValidation rest.V
|
||||
// delete immediately, or no graceful deletion supported
|
||||
klog.V(6).Infof("going to delete %s from registry: ", name)
|
||||
out = e.NewFunc()
|
||||
if err := e.Storage.Delete(ctx, key, out, &preconditions, storage.ValidateObjectFunc(deleteValidation), dryrun.IsDryRun(options.DryRun)); err != nil {
|
||||
if err := e.Storage.Delete(ctx, key, out, &preconditions, storage.ValidateObjectFunc(deleteValidation), dryrun.IsDryRun(options.DryRun), nil); err != nil {
|
||||
// Please refer to the place where we set ignoreNotFound for the reason
|
||||
// why we ignore the NotFound error .
|
||||
if storage.IsNotFound(err) && ignoreNotFound && lastExisting != nil {
|
||||
// The lastExisting object may not be the last state of the object
|
||||
// before its deletion, but it's the best approximation.
|
||||
out, err := e.finalizeDelete(ctx, lastExisting, true)
|
||||
out, err := e.finalizeDelete(ctx, lastExisting, true, options)
|
||||
return out, true, err
|
||||
}
|
||||
return nil, false, storeerr.InterpretDeleteError(err, qualifiedResource, name)
|
||||
}
|
||||
out, err = e.finalizeDelete(ctx, out, true)
|
||||
out, err = e.finalizeDelete(ctx, out, true, options)
|
||||
return out, true, err
|
||||
}
|
||||
|
||||
@@ -1006,12 +1102,19 @@ func (e *Store) DeleteCollection(ctx context.Context, deleteValidation rest.Vali
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(items) == 0 {
|
||||
// Nothing to delete, return now
|
||||
return listObj, nil
|
||||
}
|
||||
// Spawn a number of goroutines, so that we can issue requests to storage
|
||||
// in parallel to speed up deletion.
|
||||
// TODO: Make this proportional to the number of items to delete, up to
|
||||
// It is proportional to the number of items to delete, up to
|
||||
// DeleteCollectionWorkers (it doesn't make much sense to spawn 16
|
||||
// workers to delete 10 items).
|
||||
workersNumber := e.DeleteCollectionWorkers
|
||||
if workersNumber > len(items) {
|
||||
workersNumber = len(items)
|
||||
}
|
||||
if workersNumber < 1 {
|
||||
workersNumber = 1
|
||||
}
|
||||
@@ -1063,17 +1166,13 @@ func (e *Store) DeleteCollection(ctx context.Context, deleteValidation rest.Vali
|
||||
|
||||
// finalizeDelete runs the Store's AfterDelete hook if runHooks is set and
|
||||
// returns the decorated deleted object if appropriate.
|
||||
func (e *Store) finalizeDelete(ctx context.Context, obj runtime.Object, runHooks bool) (runtime.Object, error) {
|
||||
func (e *Store) finalizeDelete(ctx context.Context, obj runtime.Object, runHooks bool, options *metav1.DeleteOptions) (runtime.Object, error) {
|
||||
if runHooks && e.AfterDelete != nil {
|
||||
if err := e.AfterDelete(obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.AfterDelete(obj, options)
|
||||
}
|
||||
if e.ReturnDeletedObject {
|
||||
if e.Decorator != nil {
|
||||
if err := e.Decorator(obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.Decorator(obj)
|
||||
}
|
||||
return obj, nil
|
||||
}
|
||||
@@ -1119,9 +1218,10 @@ func (e *Store) Watch(ctx context.Context, options *metainternalversion.ListOpti
|
||||
|
||||
// WatchPredicate starts a watch for the items that matches.
|
||||
func (e *Store) WatchPredicate(ctx context.Context, p storage.SelectionPredicate, resourceVersion string) (watch.Interface, error) {
|
||||
storageOpts := storage.ListOptions{ResourceVersion: resourceVersion, Predicate: p}
|
||||
if name, ok := p.MatchesSingle(); ok {
|
||||
if key, err := e.KeyFunc(ctx, name); err == nil {
|
||||
w, err := e.Storage.Watch(ctx, key, resourceVersion, p)
|
||||
w, err := e.Storage.Watch(ctx, key, storageOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1134,7 +1234,7 @@ func (e *Store) WatchPredicate(ctx context.Context, p storage.SelectionPredicate
|
||||
// optimization is skipped
|
||||
}
|
||||
|
||||
w, err := e.Storage.WatchList(ctx, e.KeyRootFunc(ctx), resourceVersion, p)
|
||||
w, err := e.Storage.WatchList(ctx, e.KeyRootFunc(ctx), storageOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1163,44 +1263,6 @@ func (e *Store) calculateTTL(obj runtime.Object, defaultTTL int64, update bool)
|
||||
return ttl, err
|
||||
}
|
||||
|
||||
// exportObjectMeta unsets the fields on the given object that should not be
|
||||
// present when the object is exported.
|
||||
func exportObjectMeta(accessor metav1.Object, exact bool) {
|
||||
accessor.SetUID("")
|
||||
if !exact {
|
||||
accessor.SetNamespace("")
|
||||
}
|
||||
accessor.SetCreationTimestamp(metav1.Time{})
|
||||
accessor.SetDeletionTimestamp(nil)
|
||||
accessor.SetResourceVersion("")
|
||||
accessor.SetSelfLink("")
|
||||
if len(accessor.GetGenerateName()) > 0 && !exact {
|
||||
accessor.SetName("")
|
||||
}
|
||||
}
|
||||
|
||||
// Export implements the rest.Exporter interface
|
||||
func (e *Store) Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) {
|
||||
obj, err := e.Get(ctx, name, &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if accessor, err := meta.Accessor(obj); err == nil {
|
||||
exportObjectMeta(accessor, opts.Exact)
|
||||
} else {
|
||||
klog.V(4).Infof("Object of type %v does not have ObjectMeta: %v", reflect.TypeOf(obj), err)
|
||||
}
|
||||
|
||||
if e.ExportStrategy != nil {
|
||||
if err = e.ExportStrategy.Export(ctx, obj, opts.Exact); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
e.CreateStrategy.PrepareForCreate(ctx, obj)
|
||||
}
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
// CompleteWithOptions updates the store with the provided options and
|
||||
// defaults common fields.
|
||||
func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error {
|
||||
@@ -1217,6 +1279,10 @@ func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error {
|
||||
return fmt.Errorf("store for %s must set both KeyRootFunc and KeyFunc or neither", e.DefaultQualifiedResource.String())
|
||||
}
|
||||
|
||||
if e.TableConvertor == nil {
|
||||
return fmt.Errorf("store for %s must set TableConvertor; rest.NewDefaultTableConvertor(e.DefaultQualifiedResource) can be used to output just name/creation time", e.DefaultQualifiedResource.String())
|
||||
}
|
||||
|
||||
var isNamespaced bool
|
||||
switch {
|
||||
case e.CreateStrategy != nil:
|
||||
@@ -1377,13 +1443,21 @@ func (e *Store) ConvertToTable(ctx context.Context, object runtime.Object, table
|
||||
if e.TableConvertor != nil {
|
||||
return e.TableConvertor.ConvertToTable(ctx, object, tableOptions)
|
||||
}
|
||||
return rest.NewDefaultTableConvertor(e.qualifiedResourceFromContext(ctx)).ConvertToTable(ctx, object, tableOptions)
|
||||
return rest.NewDefaultTableConvertor(e.DefaultQualifiedResource).ConvertToTable(ctx, object, tableOptions)
|
||||
}
|
||||
|
||||
func (e *Store) StorageVersion() runtime.GroupVersioner {
|
||||
return e.StorageVersioner
|
||||
}
|
||||
|
||||
// GetResetFields implements rest.ResetFieldsStrategy
|
||||
func (e *Store) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
|
||||
if e.ResetFieldsStrategy == nil {
|
||||
return nil
|
||||
}
|
||||
return e.ResetFieldsStrategy.GetResetFields()
|
||||
}
|
||||
|
||||
// validateIndexers will check the prefix of indexers.
|
||||
func validateIndexers(indexers *cache.Indexers) error {
|
||||
if indexers == nil {
|
||||
|
||||
6
vendor/k8s.io/apiserver/pkg/registry/generic/storage_decorator.go
generated
vendored
6
vendor/k8s.io/apiserver/pkg/registry/generic/storage_decorator.go
generated
vendored
@@ -47,12 +47,12 @@ func UndecoratedStorage(
|
||||
getAttrsFunc storage.AttrFunc,
|
||||
trigger storage.IndexerFuncs,
|
||||
indexers *cache.Indexers) (storage.Interface, factory.DestroyFunc, error) {
|
||||
return NewRawStorage(config)
|
||||
return NewRawStorage(config, newFunc)
|
||||
}
|
||||
|
||||
// NewRawStorage creates the low level kv storage. This is a work-around for current
|
||||
// two layer of same storage interface.
|
||||
// TODO: Once cacher is enabled on all registries (event registry is special), we will remove this method.
|
||||
func NewRawStorage(config *storagebackend.Config) (storage.Interface, factory.DestroyFunc, error) {
|
||||
return factory.Create(*config)
|
||||
func NewRawStorage(config *storagebackend.Config, newFunc func() runtime.Object) (storage.Interface, factory.DestroyFunc, error) {
|
||||
return factory.Create(*config, newFunc)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user