Upgrade k8s package verison (#5358)

* upgrade k8s package version

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

* Script upgrade and code formatting.

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>
This commit is contained in:
hongzhouzi
2022-11-15 14:56:38 +08:00
committed by GitHub
parent 5f91c1663a
commit 44167aa47a
3106 changed files with 321340 additions and 172080 deletions

View File

@@ -1,26 +1,19 @@
# See the OWNERS docs at https://go.k8s.io/owners
reviewers:
- thockin
- lavalamp
- smarterclayton
- wojtek-t
- deads2k
- yujuhong
- derekwaynecarr
- caesarxuchao
- mikedanese
- liggitt
- davidopp
- saad-ali
- janetkuo
- pwittrock
- ncdc
- piosz
- dims
- hongchaodeng
- krousey
- xiang90
- resouer
- sdminonne
- enj
- thockin
- lavalamp
- smarterclayton
- wojtek-t
- deads2k
- yujuhong
- derekwaynecarr
- caesarxuchao
- mikedanese
- liggitt
- saad-ali
- janetkuo
- pwittrock
- ncdc
- dims
- enj

View File

@@ -22,18 +22,20 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/storagebackend"
flowcontrolrequest "k8s.io/apiserver/pkg/util/flowcontrol/request"
"k8s.io/client-go/tools/cache"
)
// RESTOptions is set of configuration options to generic registries.
// RESTOptions is set of resource-specific configuration options to generic registries.
type RESTOptions struct {
StorageConfig *storagebackend.Config
StorageConfig *storagebackend.ConfigForResource
Decorator StorageDecorator
EnableGarbageCollection bool
DeleteCollectionWorkers int
ResourcePrefix string
CountMetricPollPeriod time.Duration
EnableGarbageCollection bool
DeleteCollectionWorkers int
ResourcePrefix string
CountMetricPollPeriod time.Duration
StorageObjectCountTracker flowcontrolrequest.StorageObjectCountTracker
}
// Implement RESTOptionsGetter so that RESTOptions can directly be used when available (i.e. tests)

View File

@@ -29,8 +29,8 @@ type decoratedWatcher struct {
resultCh chan watch.Event
}
func newDecoratedWatcher(w watch.Interface, decorator func(runtime.Object)) *decoratedWatcher {
ctx, cancel := context.WithCancel(context.Background())
func newDecoratedWatcher(ctx context.Context, w watch.Interface, decorator func(runtime.Object)) *decoratedWatcher {
ctx, cancel := context.WithCancel(ctx)
d := &decoratedWatcher{
w: w,
decorator: decorator,
@@ -41,14 +41,18 @@ func newDecoratedWatcher(w watch.Interface, decorator func(runtime.Object)) *dec
return d
}
// run decorates watch events from the underlying watcher until its result channel
// is closed or the passed in context is done.
// When run() returns, decoratedWatcher#resultCh is closed.
func (d *decoratedWatcher) run(ctx context.Context) {
var recv, send watch.Event
var ok bool
defer close(d.resultCh)
for {
select {
case recv, ok = <-d.w.ResultChan():
// The underlying channel may be closed after timeout.
if !ok {
// The underlying channel was closed, cancel our context
d.cancel()
return
}
@@ -61,20 +65,24 @@ func (d *decoratedWatcher) run(ctx context.Context) {
}
select {
case d.resultCh <- send:
if send.Type == watch.Error {
d.cancel()
}
// propagated event successfully
case <-ctx.Done():
// context timed out or was cancelled, stop the underlying watcher
d.w.Stop()
return
}
case <-ctx.Done():
// context timed out or was cancelled, stop the underlying watcher
d.w.Stop()
close(d.resultCh)
return
}
}
}
func (d *decoratedWatcher) Stop() {
// stop the underlying watcher
d.w.Stop()
// cancel our context
d.cancel()
}

View File

@@ -60,45 +60,37 @@ func (s *DryRunnableStorage) Watch(ctx context.Context, key string, opts storage
return s.Storage.Watch(ctx, key, opts)
}
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, opts storage.GetOptions, objPtr runtime.Object) error {
return s.Storage.Get(ctx, key, opts, objPtr)
}
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, opts storage.ListOptions, listObj runtime.Object) error {
return s.Storage.List(ctx, key, opts, listObj)
func (s *DryRunnableStorage) GetList(ctx context.Context, key string, opts storage.ListOptions, listObj runtime.Object) error {
return s.Storage.GetList(ctx, key, opts, listObj)
}
func (s *DryRunnableStorage) GuaranteedUpdate(
ctx context.Context, key string, ptrToType runtime.Object, ignoreNotFound bool,
ctx context.Context, key string, destination runtime.Object, ignoreNotFound bool,
preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc, dryRun bool, cachedExistingObject runtime.Object) error {
if dryRun {
err := s.Storage.Get(ctx, key, storage.GetOptions{IgnoreNotFound: ignoreNotFound}, ptrToType)
err := s.Storage.Get(ctx, key, storage.GetOptions{IgnoreNotFound: ignoreNotFound}, destination)
if err != nil {
return err
}
err = preconditions.Check(key, ptrToType)
err = preconditions.Check(key, destination)
if err != nil {
return err
}
rev, err := s.Versioner().ObjectResourceVersion(ptrToType)
rev, err := s.Versioner().ObjectResourceVersion(destination)
if err != nil {
return err
}
out, _, err := tryUpdate(ptrToType, storage.ResponseMeta{ResourceVersion: rev})
updated, _, err := tryUpdate(destination, storage.ResponseMeta{ResourceVersion: rev})
if err != nil {
return err
}
return s.copyInto(out, ptrToType)
return s.copyInto(updated, destination)
}
return s.Storage.GuaranteedUpdate(ctx, key, ptrToType, ignoreNotFound, preconditions, tryUpdate, cachedExistingObject)
return s.Storage.GuaranteedUpdate(ctx, key, destination, ignoreNotFound, preconditions, tryUpdate, cachedExistingObject)
}
func (s *DryRunnableStorage) Count(key string) (int64, error) {

View File

@@ -27,7 +27,6 @@ import (
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/storage"
cacherstorage "k8s.io/apiserver/pkg/storage/cacher"
"k8s.io/apiserver/pkg/storage/etcd3"
"k8s.io/apiserver/pkg/storage/storagebackend"
"k8s.io/apiserver/pkg/storage/storagebackend/factory"
"k8s.io/client-go/tools/cache"
@@ -36,7 +35,7 @@ import (
// Creates a cacher based given storageConfig.
func StorageWithCacher() generic.StorageDecorator {
return func(
storageConfig *storagebackend.Config,
storageConfig *storagebackend.ConfigForResource,
resourcePrefix string,
keyFunc func(obj runtime.Object) (string, error),
newFunc func() runtime.Object,
@@ -49,13 +48,14 @@ func StorageWithCacher() generic.StorageDecorator {
if err != nil {
return s, d, err
}
if klog.V(5).Enabled() {
klog.Infof("Storage caching is enabled for %s", objectTypeToString(newFunc()))
if klogV := klog.V(5); klogV.Enabled() {
//nolint:logcheck // It complains about the key/value pairs because it cannot check them.
klogV.InfoS("Storage caching is enabled", objectTypeToArgs(newFunc())...)
}
cacherConfig := cacherstorage.Config{
Storage: s,
Versioner: etcd3.APIObjectVersioner{},
Versioner: storage.APIObjectVersioner{},
ResourcePrefix: resourcePrefix,
KeyFunc: keyFunc,
NewFunc: newFunc,
@@ -69,69 +69,26 @@ func StorageWithCacher() generic.StorageDecorator {
if err != nil {
return nil, func() {}, err
}
var once sync.Once
destroyFunc := func() {
cacher.Stop()
d()
once.Do(func() {
cacher.Stop()
d()
})
}
// TODO : Remove RegisterStorageCleanup below when PR
// https://github.com/kubernetes/kubernetes/pull/50690
// merges as that shuts down storage properly
RegisterStorageCleanup(destroyFunc)
return cacher, destroyFunc, nil
}
}
func objectTypeToString(obj runtime.Object) string {
func objectTypeToArgs(obj runtime.Object) []interface{} {
// 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)
return []interface{}{"apiVersion", apiVersion, "kind", 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
// HACK ALERT : Track the destroy methods to call them
// from the test harness. TrackStorageCleanup will be called
// only from the test harness, so Register/Cleanup will be
// no-op at runtime.
var cleanupLock sync.Mutex
var cleanup []func() = nil
func TrackStorageCleanup() {
cleanupLock.Lock()
defer cleanupLock.Unlock()
if cleanup != nil {
panic("Conflicting storage tracking")
}
cleanup = make([]func(), 0)
}
func RegisterStorageCleanup(fn func()) {
cleanupLock.Lock()
defer cleanupLock.Unlock()
if cleanup == nil {
return
}
cleanup = append(cleanup, fn)
}
func CleanupStorage() {
cleanupLock.Lock()
old := cleanup
cleanup = nil
cleanupLock.Unlock()
for _, d := range old {
d()
}
return []interface{}{"type", fmt.Sprintf("%T", obj)}
}

View File

@@ -44,6 +44,7 @@ import (
storeerr "k8s.io/apiserver/pkg/storage/errors"
"k8s.io/apiserver/pkg/storage/etcd3/metrics"
"k8s.io/apiserver/pkg/util/dryrun"
flowcontrolrequest "k8s.io/apiserver/pkg/util/flowcontrol/request"
"k8s.io/client-go/tools/cache"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
@@ -216,7 +217,10 @@ type Store struct {
// If the StorageVersioner is nil, apiserver will leave the
// storageVersionHash as empty in the discovery document.
StorageVersioner runtime.GroupVersioner
// Called to cleanup clients used by the underlying Storage; optional.
// DestroyFunc cleans up clients used by the underlying Storage; optional.
// If set, DestroyFunc has to be implemented in thread-safe way and
// be prepared for being called more than once.
DestroyFunc func()
}
@@ -278,6 +282,13 @@ func (e *Store) New() runtime.Object {
return e.NewFunc()
}
// Destroy cleans up its resources on shutdown.
func (e *Store) Destroy() {
if e.DestroyFunc != nil {
e.DestroyFunc()
}
}
// NewList implements rest.Lister.
func (e *Store) NewList() runtime.Object {
return e.NewListFunc()
@@ -292,7 +303,7 @@ func (e *Store) NamespaceScoped() bool {
return e.UpdateStrategy.NamespaceScoped()
}
panic("programmer error: no CRUD for resource, you're crazy, override NamespaceScoped too")
panic("programmer error: no CRUD for resource, override NamespaceScoped too")
}
// GetCreateStrategy implements GenericStore.
@@ -342,16 +353,22 @@ 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}
storageOpts := storage.ListOptions{
ResourceVersion: options.ResourceVersion,
ResourceVersionMatch: options.ResourceVersionMatch,
Predicate: p,
Recursive: true,
}
if name, ok := p.MatchesSingle(); ok {
if key, err := e.KeyFunc(ctx, name); err == nil {
err := e.Storage.GetToList(ctx, key, storageOpts, list)
storageOpts.Recursive = false
err := e.Storage.GetList(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), storageOpts, list)
err := e.Storage.GetList(ctx, e.KeyRootFunc(ctx), storageOpts, list)
return list, storeerr.InterpretListError(err, qualifiedResource)
}
@@ -359,9 +376,19 @@ func (e *Store) ListPredicate(ctx context.Context, p storage.SelectionPredicate,
func finishNothing(context.Context, bool) {}
// Create inserts a new item according to the unique key from the object.
// Note that registries may mutate the input object (e.g. in the strategy
// hooks). Tests which call this might want to call DeepCopy if they expect to
// be able to examine the input and output objects for differences.
func (e *Store) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
var finishCreate FinishFunc = finishNothing
// Init metadata as early as possible.
if objectMeta, err := meta.Accessor(obj); err != nil {
return nil, err
} else {
rest.FillObjectMetaSystemFields(objectMeta)
}
if e.BeginCreate != nil {
fn, err := e.BeginCreate(ctx, obj, options)
if err != nil {
@@ -400,7 +427,7 @@ func (e *Store) Create(ctx context.Context, obj runtime.Object, createValidation
out := e.NewFunc()
if err := e.Storage.Create(ctx, key, obj, out, ttl, dryrun.IsDryRun(options.DryRun)); err != nil {
err = storeerr.InterpretCreateError(err, qualifiedResource, name)
err = rest.CheckGeneratedNameError(e.CreateStrategy, err, obj)
err = rest.CheckGeneratedNameError(ctx, e.CreateStrategy, err, obj)
if !apierrors.IsAlreadyExists(err) {
return nil, err
}
@@ -464,7 +491,7 @@ func ShouldDeleteDuringUpdate(ctx context.Context, key string, obj, existing run
// 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, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
out := e.NewFunc()
klog.V(6).Infof("going to delete %s from registry, triggered by update", name)
klog.V(6).InfoS("Going to delete object from registry, triggered by update", "object", klog.KRef(genericapirequest.NamespaceValue(ctx), 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.IsDryRun(options.DryRun), nil); err != nil {
// Deletion is racy, i.e., there could be multiple update
@@ -538,6 +565,13 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
doUnconditionalUpdate := newResourceVersion == 0 && e.UpdateStrategy.AllowUnconditionalUpdate()
if existingResourceVersion == 0 {
// Init metadata as early as possible.
if objectMeta, err := meta.Accessor(obj); err != nil {
return nil, nil, err
} else {
rest.FillObjectMetaSystemFields(objectMeta)
}
var finishCreate FinishFunc = finishNothing
if e.BeginCreate != nil {
@@ -655,7 +689,7 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
}
if creating {
err = storeerr.InterpretCreateError(err, qualifiedResource, name)
err = rest.CheckGeneratedNameError(e.CreateStrategy, err, creatingObj)
err = rest.CheckGeneratedNameError(ctx, e.CreateStrategy, err, creatingObj)
} else {
err = storeerr.InterpretUpdateError(err, qualifiedResource, name)
}
@@ -681,8 +715,9 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
// create-on-update path.
func newCreateOptionsFromUpdateOptions(in *metav1.UpdateOptions) *metav1.CreateOptions {
co := &metav1.CreateOptions{
DryRun: in.DryRun,
FieldManager: in.FieldManager,
DryRun: in.DryRun,
FieldManager: in.FieldManager,
FieldValidation: in.FieldValidation,
}
co.TypeMeta.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("CreateOptions"))
return co
@@ -749,9 +784,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
//nolint:staticcheck // SA1019 backwards compatibility
if options != nil && options.OrphanDependents != nil {
//lint:ignore SA1019 backwards compatibility
//nolint:staticcheck // SA1019 backwards compatibility
return *options.OrphanDependents
}
if options != nil && options.PropagationPolicy != nil {
@@ -792,7 +827,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
//nolint:staticcheck // SA1019 backwards compatibility
if options != nil && options.OrphanDependents != nil {
return false
}
@@ -889,13 +924,13 @@ func markAsDeleting(obj runtime.Object, now time.Time) (err error) {
// grace period seconds (graceful deletion) and updating the list of
// finalizers (finalization); it returns:
//
// 1. an error
// 2. a boolean indicating that the object was not found, but it should be
// ignored
// 3. a boolean indicating that the object's grace period is exhausted and it
// should be deleted immediately
// 4. a new output object with the state that was updated
// 5. a copy of the last existing state of the object
// 1. an error
// 2. a boolean indicating that the object was not found, but it should be
// ignored
// 3. a boolean indicating that the object's grace period is exhausted and it
// should be deleted immediately
// 4. a new output object with the state that was updated
// 5. a copy of the last existing state of the object
func (e *Store) updateForGracefulDeletionAndFinalizers(ctx context.Context, name, key string, options *metav1.DeleteOptions, preconditions storage.Preconditions, deleteValidation rest.ValidateObjectFunc, in runtime.Object) (err error, ignoreNotFound, deleteImmediately bool, out, lastExisting runtime.Object) {
lastGraceful := int64(0)
var pendingFinalizers bool
@@ -935,7 +970,8 @@ func (e *Store) updateForGracefulDeletionAndFinalizers(ctx context.Context, name
if !graceful {
// set the DeleteGracePeriods to 0 if the object has pendingFinalizers but not supporting graceful deletion
if pendingFinalizers {
klog.V(6).Infof("update the DeletionTimestamp to \"now\" and GracePeriodSeconds to 0 for object %s, because it has pending finalizers", name)
klog.V(6).InfoS("Object has pending finalizers, so the registry is going to update its status to deleting",
"object", klog.KRef(genericapirequest.NamespaceValue(ctx), name), "gracePeriod", time.Second*0)
err = markAsDeleting(existing, time.Now())
if err != nil {
return nil, err
@@ -981,6 +1017,7 @@ func (e *Store) updateForGracefulDeletionAndFinalizers(ctx context.Context, name
}
// Delete removes the item from storage.
// options can be mutated by rest.BeforeDelete due to a graceful deletion strategy.
func (e *Store) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
key, err := e.KeyFunc(ctx, name)
if err != nil {
@@ -1055,7 +1092,7 @@ 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)
klog.V(6).InfoS("Going to delete object from registry", "object", klog.KRef(genericapirequest.NamespaceValue(ctx), name))
out = e.NewFunc()
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
@@ -1121,13 +1158,21 @@ func (e *Store) DeleteCollection(ctx context.Context, deleteValidation rest.Vali
wg := sync.WaitGroup{}
toProcess := make(chan int, 2*workersNumber)
errs := make(chan error, workersNumber+1)
workersExited := make(chan struct{})
distributorExited := make(chan struct{})
go func() {
defer utilruntime.HandleCrash(func(panicReason interface{}) {
errs <- fmt.Errorf("DeleteCollection distributor panicked: %v", panicReason)
})
defer close(distributorExited)
for i := 0; i < len(items); i++ {
toProcess <- i
select {
case toProcess <- i:
case <-workersExited:
klog.V(4).InfoS("workers already exited, and there are some items waiting to be processed", "finished", i, "total", len(items))
return
}
}
close(toProcess)
}()
@@ -1147,8 +1192,12 @@ func (e *Store) DeleteCollection(ctx context.Context, deleteValidation rest.Vali
errs <- err
return
}
if _, _, err := e.Delete(ctx, accessor.GetName(), deleteValidation, options); err != nil && !apierrors.IsNotFound(err) {
klog.V(4).Infof("Delete %s in DeleteCollection failed: %v", accessor.GetName(), err)
// DeepCopy the deletion options because individual graceful deleters communicate changes via a mutating
// function in the delete strategy called in the delete method. While that is always ugly, it works
// when making a single call. When making multiple calls via delete collection, the mutation applied to
// pod/A can change the option ultimately used for pod/B.
if _, _, err := e.Delete(ctx, accessor.GetName(), deleteValidation, options.DeepCopy()); err != nil && !apierrors.IsNotFound(err) {
klog.V(4).InfoS("Delete object in DeleteCollection failed", "object", klog.KObj(accessor), "err", err)
errs <- err
return
}
@@ -1156,6 +1205,9 @@ func (e *Store) DeleteCollection(ctx context.Context, deleteValidation rest.Vali
}()
}
wg.Wait()
// notify distributor to exit
close(workersExited)
<-distributorExited
select {
case err := <-errs:
return nil, err
@@ -1218,28 +1270,24 @@ 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}
storageOpts := storage.ListOptions{ResourceVersion: resourceVersion, Predicate: p, Recursive: true}
key := e.KeyRootFunc(ctx)
if name, ok := p.MatchesSingle(); ok {
if key, err := e.KeyFunc(ctx, name); err == nil {
w, err := e.Storage.Watch(ctx, key, storageOpts)
if err != nil {
return nil, err
}
if e.Decorator != nil {
return newDecoratedWatcher(w, e.Decorator), nil
}
return w, nil
if k, err := e.KeyFunc(ctx, name); err == nil {
key = k
storageOpts.Recursive = false
}
// if we cannot extract a key based on the current context, the
// optimization is skipped
}
w, err := e.Storage.WatchList(ctx, e.KeyRootFunc(ctx), storageOpts)
w, err := e.Storage.Watch(ctx, key, storageOpts)
if err != nil {
return nil, err
}
if e.Decorator != nil {
return newDecoratedWatcher(w, e.Decorator), nil
return newDecoratedWatcher(ctx, w, e.Decorator), nil
}
return w, nil
}
@@ -1407,13 +1455,16 @@ func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error {
e.StorageVersioner = opts.StorageConfig.EncodeVersioner
if opts.CountMetricPollPeriod > 0 {
stopFunc := e.startObservingCount(opts.CountMetricPollPeriod)
stopFunc := e.startObservingCount(opts.CountMetricPollPeriod, opts.StorageObjectCountTracker)
previousDestroy := e.DestroyFunc
var once sync.Once
e.DestroyFunc = func() {
stopFunc()
if previousDestroy != nil {
previousDestroy()
}
once.Do(func() {
stopFunc()
if previousDestroy != nil {
previousDestroy()
}
})
}
}
}
@@ -1422,18 +1473,21 @@ func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error {
}
// startObservingCount starts monitoring given prefix and periodically updating metrics. It returns a function to stop collection.
func (e *Store) startObservingCount(period time.Duration) func() {
func (e *Store) startObservingCount(period time.Duration, objectCountTracker flowcontrolrequest.StorageObjectCountTracker) func() {
prefix := e.KeyRootFunc(genericapirequest.NewContext())
resourceName := e.DefaultQualifiedResource.String()
klog.V(2).Infof("Monitoring %v count at <storage-prefix>/%v", resourceName, prefix)
klog.V(2).InfoS("Monitoring resource count at path", "resource", resourceName, "path", "<storage-prefix>/"+prefix)
stopCh := make(chan struct{})
go wait.JitterUntil(func() {
count, err := e.Storage.Count(prefix)
if err != nil {
klog.V(5).Infof("Failed to update storage count metric: %v", err)
metrics.UpdateObjectCount(resourceName, -1)
} else {
metrics.UpdateObjectCount(resourceName, count)
klog.V(5).InfoS("Failed to update storage count metric", "err", err)
count = -1
}
metrics.UpdateObjectCount(resourceName, count)
if objectCountTracker != nil {
objectCountTracker.Set(resourceName, count)
}
}, period, resourceCountPollPeriodJitter, true, stopCh)
return func() { close(stopCh) }

View File

@@ -27,7 +27,7 @@ import (
// StorageDecorator is a function signature for producing a storage.Interface
// and an associated DestroyFunc from given parameters.
type StorageDecorator func(
config *storagebackend.Config,
config *storagebackend.ConfigForResource,
resourcePrefix string,
keyFunc func(obj runtime.Object) (string, error),
newFunc func() runtime.Object,
@@ -39,7 +39,7 @@ type StorageDecorator func(
// UndecoratedStorage returns the given a new storage from the given config
// without any decoration.
func UndecoratedStorage(
config *storagebackend.Config,
config *storagebackend.ConfigForResource,
resourcePrefix string,
keyFunc func(obj runtime.Object) (string, error),
newFunc func() runtime.Object,
@@ -53,6 +53,6 @@ func UndecoratedStorage(
// 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, newFunc func() runtime.Object) (storage.Interface, factory.DestroyFunc, error) {
func NewRawStorage(config *storagebackend.ConfigForResource, newFunc func() runtime.Object) (storage.Interface, factory.DestroyFunc, error) {
return factory.Create(*config, newFunc)
}