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:
39
vendor/k8s.io/apiserver/pkg/registry/generic/OWNERS
generated
vendored
39
vendor/k8s.io/apiserver/pkg/registry/generic/OWNERS
generated
vendored
@@ -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
|
||||
|
||||
14
vendor/k8s.io/apiserver/pkg/registry/generic/options.go
generated
vendored
14
vendor/k8s.io/apiserver/pkg/registry/generic/options.go
generated
vendored
@@ -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)
|
||||
|
||||
22
vendor/k8s.io/apiserver/pkg/registry/generic/registry/decorated_watcher.go
generated
vendored
22
vendor/k8s.io/apiserver/pkg/registry/generic/registry/decorated_watcher.go
generated
vendored
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
26
vendor/k8s.io/apiserver/pkg/registry/generic/registry/dryrun.go
generated
vendored
26
vendor/k8s.io/apiserver/pkg/registry/generic/registry/dryrun.go
generated
vendored
@@ -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) {
|
||||
|
||||
71
vendor/k8s.io/apiserver/pkg/registry/generic/registry/storage_factory.go
generated
vendored
71
vendor/k8s.io/apiserver/pkg/registry/generic/registry/storage_factory.go
generated
vendored
@@ -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)}
|
||||
}
|
||||
|
||||
150
vendor/k8s.io/apiserver/pkg/registry/generic/registry/store.go
generated
vendored
150
vendor/k8s.io/apiserver/pkg/registry/generic/registry/store.go
generated
vendored
@@ -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) }
|
||||
|
||||
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
@@ -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)
|
||||
}
|
||||
|
||||
30
vendor/k8s.io/apiserver/pkg/registry/rest/OWNERS
generated
vendored
30
vendor/k8s.io/apiserver/pkg/registry/rest/OWNERS
generated
vendored
@@ -1,20 +1,16 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
reviewers:
|
||||
- thockin
|
||||
- smarterclayton
|
||||
- wojtek-t
|
||||
- deads2k
|
||||
- brendandburns
|
||||
- derekwaynecarr
|
||||
- caesarxuchao
|
||||
- mikedanese
|
||||
- liggitt
|
||||
- justinsb
|
||||
- ncdc
|
||||
- dims
|
||||
- hongchaodeng
|
||||
- krousey
|
||||
- ingvagabund
|
||||
- sdminonne
|
||||
- enj
|
||||
- thockin
|
||||
- smarterclayton
|
||||
- wojtek-t
|
||||
- deads2k
|
||||
- derekwaynecarr
|
||||
- caesarxuchao
|
||||
- mikedanese
|
||||
- liggitt
|
||||
- justinsb
|
||||
- ncdc
|
||||
- dims
|
||||
- ingvagabund
|
||||
- enj
|
||||
|
||||
71
vendor/k8s.io/apiserver/pkg/registry/rest/create.go
generated
vendored
71
vendor/k8s.io/apiserver/pkg/registry/rest/create.go
generated
vendored
@@ -18,6 +18,7 @@ package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
@@ -28,9 +29,11 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/apiserver/pkg/warning"
|
||||
)
|
||||
|
||||
// RESTCreateStrategy defines the minimum validation, accepted input, and
|
||||
@@ -59,6 +62,26 @@ type RESTCreateStrategy interface {
|
||||
// before the object is persisted. This method should not mutate the
|
||||
// object.
|
||||
Validate(ctx context.Context, obj runtime.Object) field.ErrorList
|
||||
// WarningsOnCreate returns warnings to the client performing a create.
|
||||
// WarningsOnCreate is invoked after default fields in the object have been filled in
|
||||
// and after Validate has passed, before Canonicalize is called, and the object is persisted.
|
||||
// This method must not mutate the object.
|
||||
//
|
||||
// Be brief; limit warnings to 120 characters if possible.
|
||||
// Don't include a "Warning:" prefix in the message (that is added by clients on output).
|
||||
// Warnings returned about a specific field should be formatted as "path.to.field: message".
|
||||
// For example: `spec.imagePullSecrets[0].name: invalid empty name ""`
|
||||
//
|
||||
// Use warning messages to describe problems the client making the API request should correct or be aware of.
|
||||
// For example:
|
||||
// - use of deprecated fields/labels/annotations that will stop working in a future release
|
||||
// - use of obsolete fields/labels/annotations that are non-functional
|
||||
// - malformed or invalid specifications that prevent successful handling of the submitted object,
|
||||
// but are not rejected by validation for compatibility reasons
|
||||
//
|
||||
// Warnings should not be returned for fields which cannot be resolved by the caller.
|
||||
// For example, do not warn about spec fields in a subresource creation request.
|
||||
WarningsOnCreate(ctx context.Context, obj runtime.Object) []string
|
||||
// Canonicalize allows an object to be mutated into a canonical form. This
|
||||
// ensures that code that operates on these objects can rely on the common
|
||||
// form for things like comparison. Canonicalize is invoked after
|
||||
@@ -77,17 +100,22 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx context.Context, obj runtime.
|
||||
return kerr
|
||||
}
|
||||
|
||||
if strategy.NamespaceScoped() {
|
||||
if !ValidNamespace(ctx, objectMeta) {
|
||||
return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
|
||||
}
|
||||
} else if len(objectMeta.GetNamespace()) > 0 {
|
||||
objectMeta.SetNamespace(metav1.NamespaceNone)
|
||||
// ensure that system-critical metadata has been populated
|
||||
if !metav1.HasObjectMetaSystemFieldValues(objectMeta) {
|
||||
return errors.NewInternalError(fmt.Errorf("system metadata was not initialized"))
|
||||
}
|
||||
objectMeta.SetDeletionTimestamp(nil)
|
||||
objectMeta.SetDeletionGracePeriodSeconds(nil)
|
||||
|
||||
// ensure namespace on the object is correct, or error if a conflicting namespace was set in the object
|
||||
requestNamespace, ok := genericapirequest.NamespaceFrom(ctx)
|
||||
if !ok {
|
||||
return errors.NewInternalError(fmt.Errorf("no namespace information found in request context"))
|
||||
}
|
||||
if err := EnsureObjectNamespaceMatchesRequestNamespace(ExpectedNamespaceForScope(requestNamespace, strategy.NamespaceScoped()), objectMeta); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
strategy.PrepareForCreate(ctx, obj)
|
||||
FillObjectMetaSystemFields(objectMeta)
|
||||
|
||||
if len(objectMeta.GetGenerateName()) > 0 && len(objectMeta.GetName()) == 0 {
|
||||
objectMeta.SetName(strategy.GenerateName(objectMeta.GetGenerateName()))
|
||||
}
|
||||
@@ -97,11 +125,6 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx context.Context, obj runtime.
|
||||
objectMeta.SetManagedFields(nil)
|
||||
}
|
||||
|
||||
// ClusterName is ignored and should not be saved
|
||||
if len(objectMeta.GetClusterName()) > 0 {
|
||||
objectMeta.SetClusterName("")
|
||||
}
|
||||
|
||||
if errs := strategy.Validate(ctx, obj); len(errs) > 0 {
|
||||
return errors.NewInvalid(kind.GroupKind(), objectMeta.GetName(), errs)
|
||||
}
|
||||
@@ -113,6 +136,10 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx context.Context, obj runtime.
|
||||
return errors.NewInvalid(kind.GroupKind(), objectMeta.GetName(), errs)
|
||||
}
|
||||
|
||||
for _, w := range strategy.WarningsOnCreate(ctx, obj) {
|
||||
warning.AddWarning(ctx, "", w)
|
||||
}
|
||||
|
||||
strategy.Canonicalize(obj)
|
||||
|
||||
return nil
|
||||
@@ -120,21 +147,31 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx context.Context, obj runtime.
|
||||
|
||||
// CheckGeneratedNameError checks whether an error that occurred creating a resource is due
|
||||
// to generation being unable to pick a valid name.
|
||||
func CheckGeneratedNameError(strategy RESTCreateStrategy, err error, obj runtime.Object) error {
|
||||
func CheckGeneratedNameError(ctx context.Context, strategy RESTCreateStrategy, err error, obj runtime.Object) error {
|
||||
if !errors.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
objectMeta, kind, kerr := objectMetaAndKind(strategy, obj)
|
||||
objectMeta, gvk, kerr := objectMetaAndKind(strategy, obj)
|
||||
if kerr != nil {
|
||||
return kerr
|
||||
}
|
||||
|
||||
if len(objectMeta.GetGenerateName()) == 0 {
|
||||
// If we don't have a generated name, return the original error (AlreadyExists).
|
||||
// When we're here, the user picked a name that is causing a conflict.
|
||||
return err
|
||||
}
|
||||
|
||||
return errors.NewServerTimeoutForKind(kind.GroupKind(), "POST", 0)
|
||||
// Get the group resource information from the context, if populated.
|
||||
gr := schema.GroupResource{}
|
||||
if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found {
|
||||
gr = schema.GroupResource{Group: gvk.Group, Resource: requestInfo.Resource}
|
||||
}
|
||||
|
||||
// If we have a name and generated name, the server picked a name
|
||||
// that already exists.
|
||||
return errors.NewGenerateNameConflict(gr, objectMeta.GetName(), 1)
|
||||
}
|
||||
|
||||
// objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error.
|
||||
|
||||
20
vendor/k8s.io/apiserver/pkg/registry/rest/create_update.go
generated
vendored
20
vendor/k8s.io/apiserver/pkg/registry/rest/create_update.go
generated
vendored
@@ -39,6 +39,26 @@ type RESTCreateUpdateStrategy interface {
|
||||
// filled in before the object is persisted. This method should not mutate
|
||||
// the object.
|
||||
ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList
|
||||
// WarningsOnUpdate returns warnings to the client performing the update.
|
||||
// WarningsOnUpdate is invoked after default fields in the object have been filled in
|
||||
// and after ValidateUpdate has passed, before Canonicalize is called, and before the object is persisted.
|
||||
// This method must not mutate either object.
|
||||
//
|
||||
// Be brief; limit warnings to 120 characters if possible.
|
||||
// Don't include a "Warning:" prefix in the message (that is added by clients on output).
|
||||
// Warnings returned about a specific field should be formatted as "path.to.field: message".
|
||||
// For example: `spec.imagePullSecrets[0].name: invalid empty name ""`
|
||||
//
|
||||
// Use warning messages to describe problems the client making the API request should correct or be aware of.
|
||||
// For example:
|
||||
// - use of deprecated fields/labels/annotations that will stop working in a future release
|
||||
// - use of obsolete fields/labels/annotations that are non-functional
|
||||
// - malformed or invalid specifications that prevent successful handling of the submitted object,
|
||||
// but are not rejected by validation for compatibility reasons
|
||||
//
|
||||
// Warnings should not be returned for fields which cannot be resolved by the caller.
|
||||
// For example, do not warn about spec fields in a status update.
|
||||
WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string
|
||||
// AllowUnconditionalUpdate returns true if the object can be updated
|
||||
// unconditionally (irrespective of the latest resource version), when
|
||||
// there is no resource version specified in the object.
|
||||
|
||||
19
vendor/k8s.io/apiserver/pkg/registry/rest/delete.go
generated
vendored
19
vendor/k8s.io/apiserver/pkg/registry/rest/delete.go
generated
vendored
@@ -27,6 +27,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
// RESTDeleteStrategy defines deletion behavior on an object that follows Kubernetes
|
||||
@@ -57,6 +58,8 @@ type GarbageCollectionDeleteStrategy interface {
|
||||
type RESTGracefulDeleteStrategy interface {
|
||||
// CheckGracefulDelete should return true if the object can be gracefully deleted and set
|
||||
// any default values on the DeleteOptions.
|
||||
// NOTE: if return true, `options.GracePeriodSeconds` must be non-nil (nil will fail),
|
||||
// that's what tells the deletion how "graceful" to be.
|
||||
CheckGracefulDelete(ctx context.Context, obj runtime.Object, options *metav1.DeleteOptions) bool
|
||||
}
|
||||
|
||||
@@ -86,6 +89,15 @@ func BeforeDelete(strategy RESTDeleteStrategy, ctx context.Context, obj runtime.
|
||||
return false, false, errors.NewConflict(schema.GroupResource{Group: gvk.Group, Resource: gvk.Kind}, objectMeta.GetName(), fmt.Errorf("the ResourceVersion in the precondition (%s) does not match the ResourceVersion in record (%s). The object might have been modified", *options.Preconditions.ResourceVersion, objectMeta.GetResourceVersion()))
|
||||
}
|
||||
}
|
||||
|
||||
// Negative values will be treated as the value `1s` on the delete path.
|
||||
if gracePeriodSeconds := options.GracePeriodSeconds; gracePeriodSeconds != nil && *gracePeriodSeconds < 0 {
|
||||
options.GracePeriodSeconds = utilpointer.Int64(1)
|
||||
}
|
||||
if deletionGracePeriodSeconds := objectMeta.GetDeletionGracePeriodSeconds(); deletionGracePeriodSeconds != nil && *deletionGracePeriodSeconds < 0 {
|
||||
objectMeta.SetDeletionGracePeriodSeconds(utilpointer.Int64(1))
|
||||
}
|
||||
|
||||
gracefulStrategy, ok := strategy.(RESTGracefulDeleteStrategy)
|
||||
if !ok {
|
||||
// If we're not deleting gracefully there's no point in updating Generation, as we won't update
|
||||
@@ -126,9 +138,15 @@ func BeforeDelete(strategy RESTDeleteStrategy, ctx context.Context, obj runtime.
|
||||
return false, true, nil
|
||||
}
|
||||
|
||||
// `CheckGracefulDelete` will be implemented by specific strategy
|
||||
if !gracefulStrategy.CheckGracefulDelete(ctx, obj, options) {
|
||||
return false, false, nil
|
||||
}
|
||||
|
||||
if options.GracePeriodSeconds == nil {
|
||||
return false, false, errors.NewInternalError(fmt.Errorf("options.GracePeriodSeconds should not be nil"))
|
||||
}
|
||||
|
||||
now := metav1.NewTime(metav1.Now().Add(time.Second * time.Duration(*options.GracePeriodSeconds)))
|
||||
objectMeta.SetDeletionTimestamp(&now)
|
||||
objectMeta.SetDeletionGracePeriodSeconds(options.GracePeriodSeconds)
|
||||
@@ -139,6 +157,7 @@ func BeforeDelete(strategy RESTDeleteStrategy, ctx context.Context, obj runtime.
|
||||
if objectMeta.GetGeneration() > 0 {
|
||||
objectMeta.SetGeneration(objectMeta.GetGeneration() + 1)
|
||||
}
|
||||
|
||||
return true, false, nil
|
||||
}
|
||||
|
||||
|
||||
62
vendor/k8s.io/apiserver/pkg/registry/rest/meta.go
generated
vendored
62
vendor/k8s.io/apiserver/pkg/registry/rest/meta.go
generated
vendored
@@ -17,27 +17,65 @@ limitations under the License.
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
// WipeObjectMetaSystemFields erases fields that are managed by the system on ObjectMeta.
|
||||
func WipeObjectMetaSystemFields(meta metav1.Object) {
|
||||
meta.SetCreationTimestamp(metav1.Time{})
|
||||
meta.SetUID("")
|
||||
meta.SetDeletionTimestamp(nil)
|
||||
meta.SetDeletionGracePeriodSeconds(nil)
|
||||
meta.SetSelfLink("")
|
||||
}
|
||||
|
||||
// FillObjectMetaSystemFields populates fields that are managed by the system on ObjectMeta.
|
||||
func FillObjectMetaSystemFields(meta metav1.Object) {
|
||||
meta.SetCreationTimestamp(metav1.Now())
|
||||
meta.SetUID(uuid.NewUUID())
|
||||
meta.SetSelfLink("")
|
||||
}
|
||||
|
||||
// ValidNamespace returns false if the namespace on the context differs from
|
||||
// the resource. If the resource has no namespace, it is set to the value in
|
||||
// the context.
|
||||
func ValidNamespace(ctx context.Context, resource metav1.Object) bool {
|
||||
ns, ok := genericapirequest.NamespaceFrom(ctx)
|
||||
if len(resource.GetNamespace()) == 0 {
|
||||
resource.SetNamespace(ns)
|
||||
// EnsureObjectNamespaceMatchesRequestNamespace returns an error if obj.Namespace and requestNamespace
|
||||
// are both populated and do not match. If either is unpopulated, it modifies obj as needed to ensure
|
||||
// obj.GetNamespace() == requestNamespace.
|
||||
func EnsureObjectNamespaceMatchesRequestNamespace(requestNamespace string, obj metav1.Object) error {
|
||||
objNamespace := obj.GetNamespace()
|
||||
switch {
|
||||
case objNamespace == requestNamespace:
|
||||
// already matches, no-op
|
||||
return nil
|
||||
|
||||
case objNamespace == metav1.NamespaceNone:
|
||||
// unset, default to request namespace
|
||||
obj.SetNamespace(requestNamespace)
|
||||
return nil
|
||||
|
||||
case requestNamespace == metav1.NamespaceNone:
|
||||
// cluster-scoped, clear namespace
|
||||
obj.SetNamespace(metav1.NamespaceNone)
|
||||
return nil
|
||||
|
||||
default:
|
||||
// mismatch, error
|
||||
return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
|
||||
}
|
||||
return ns == resource.GetNamespace() && ok
|
||||
}
|
||||
|
||||
// ExpectedNamespaceForScope returns the expected namespace for a resource, given the request namespace and resource scope.
|
||||
func ExpectedNamespaceForScope(requestNamespace string, namespaceScoped bool) string {
|
||||
if namespaceScoped {
|
||||
return requestNamespace
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ExpectedNamespaceForResource returns the expected namespace for a resource, given the request namespace.
|
||||
func ExpectedNamespaceForResource(requestNamespace string, resource schema.GroupVersionResource) string {
|
||||
if resource.Resource == "namespaces" && resource.Group == "" {
|
||||
return ""
|
||||
}
|
||||
return requestNamespace
|
||||
}
|
||||
|
||||
17
vendor/k8s.io/apiserver/pkg/registry/rest/rest.go
generated
vendored
17
vendor/k8s.io/apiserver/pkg/registry/rest/rest.go
generated
vendored
@@ -56,6 +56,11 @@ type Storage interface {
|
||||
// New returns an empty object that can be used with Create and Update after request data has been put into it.
|
||||
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
|
||||
New() runtime.Object
|
||||
|
||||
// Destroy cleans up its resources on shutdown.
|
||||
// Destroy has to be implemented in thread-safe way and be prepared
|
||||
// for being called more than once.
|
||||
Destroy()
|
||||
}
|
||||
|
||||
// Scoper indicates what scope the resource is at. It must be specified.
|
||||
@@ -92,6 +97,13 @@ type GroupVersionKindProvider interface {
|
||||
GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind
|
||||
}
|
||||
|
||||
// GroupVersionAcceptor is used to determine if a particular GroupVersion is acceptable to send to an endpoint.
|
||||
// This is used for endpoints which accept multiple versions (which is extremely rare).
|
||||
// The only known instance is pods/evictions which accepts policy/v1, but also policy/v1beta1 for backwards compatibility.
|
||||
type GroupVersionAcceptor interface {
|
||||
AcceptsGroupVersion(gv schema.GroupVersion) bool
|
||||
}
|
||||
|
||||
// Lister is an object that can retrieve resources that match the provided field and label criteria.
|
||||
type Lister interface {
|
||||
// NewList returns an empty object that can be used with the List call.
|
||||
@@ -271,6 +283,11 @@ type StandardStorage interface {
|
||||
GracefulDeleter
|
||||
CollectionDeleter
|
||||
Watcher
|
||||
|
||||
// Destroy cleans up its resources on shutdown.
|
||||
// Destroy has to be implemented in thread-safe way and be prepared
|
||||
// for being called more than once.
|
||||
Destroy()
|
||||
}
|
||||
|
||||
// Redirector know how to return a remote resource's location.
|
||||
|
||||
2
vendor/k8s.io/apiserver/pkg/registry/rest/table.go
generated
vendored
2
vendor/k8s.io/apiserver/pkg/registry/rest/table.go
generated
vendored
@@ -70,13 +70,11 @@ func (c defaultTableConvertor) ConvertToTable(ctx context.Context, object runtim
|
||||
}
|
||||
if m, err := meta.ListAccessor(object); err == nil {
|
||||
table.ResourceVersion = m.GetResourceVersion()
|
||||
table.SelfLink = m.GetSelfLink()
|
||||
table.Continue = m.GetContinue()
|
||||
table.RemainingItemCount = m.GetRemainingItemCount()
|
||||
} else {
|
||||
if m, err := meta.CommonAccessor(object); err == nil {
|
||||
table.ResourceVersion = m.GetResourceVersion()
|
||||
table.SelfLink = m.GetSelfLink()
|
||||
}
|
||||
}
|
||||
if opt, ok := tableOptions.(*metav1.TableOptions); !ok || !opt.NoHeaders {
|
||||
|
||||
44
vendor/k8s.io/apiserver/pkg/registry/rest/update.go
generated
vendored
44
vendor/k8s.io/apiserver/pkg/registry/rest/update.go
generated
vendored
@@ -28,8 +28,10 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/apiserver/pkg/warning"
|
||||
)
|
||||
|
||||
// RESTUpdateStrategy defines the minimum validation, accepted input, and
|
||||
@@ -51,6 +53,26 @@ type RESTUpdateStrategy interface {
|
||||
// filled in before the object is persisted. This method should not mutate
|
||||
// the object.
|
||||
ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList
|
||||
// WarningsOnUpdate returns warnings to the client performing the update.
|
||||
// WarningsOnUpdate is invoked after default fields in the object have been filled in
|
||||
// and after ValidateUpdate has passed, before Canonicalize is called, and before the object is persisted.
|
||||
// This method must not mutate either object.
|
||||
//
|
||||
// Be brief; limit warnings to 120 characters if possible.
|
||||
// Don't include a "Warning:" prefix in the message (that is added by clients on output).
|
||||
// Warnings returned about a specific field should be formatted as "path.to.field: message".
|
||||
// For example: `spec.imagePullSecrets[0].name: invalid empty name ""`
|
||||
//
|
||||
// Use warning messages to describe problems the client making the API request should correct or be aware of.
|
||||
// For example:
|
||||
// - use of deprecated fields/labels/annotations that will stop working in a future release
|
||||
// - use of obsolete fields/labels/annotations that are non-functional
|
||||
// - malformed or invalid specifications that prevent successful handling of the submitted object,
|
||||
// but are not rejected by validation for compatibility reasons
|
||||
//
|
||||
// Warnings should not be returned for fields which cannot be resolved by the caller.
|
||||
// For example, do not warn about spec fields in a status update.
|
||||
WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string
|
||||
// Canonicalize allows an object to be mutated into a canonical form. This
|
||||
// ensures that code that operates on these objects can rely on the common
|
||||
// form for things like comparison. Canonicalize is invoked after
|
||||
@@ -89,12 +111,14 @@ func BeforeUpdate(strategy RESTUpdateStrategy, ctx context.Context, obj, old run
|
||||
if kerr != nil {
|
||||
return kerr
|
||||
}
|
||||
if strategy.NamespaceScoped() {
|
||||
if !ValidNamespace(ctx, objectMeta) {
|
||||
return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
|
||||
}
|
||||
} else if len(objectMeta.GetNamespace()) > 0 {
|
||||
objectMeta.SetNamespace(metav1.NamespaceNone)
|
||||
|
||||
// ensure namespace on the object is correct, or error if a conflicting namespace was set in the object
|
||||
requestNamespace, ok := genericapirequest.NamespaceFrom(ctx)
|
||||
if !ok {
|
||||
return errors.NewInternalError(fmt.Errorf("no namespace information found in request context"))
|
||||
}
|
||||
if err := EnsureObjectNamespaceMatchesRequestNamespace(ExpectedNamespaceForScope(requestNamespace, strategy.NamespaceScoped()), objectMeta); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure requests cannot update generation
|
||||
@@ -112,10 +136,6 @@ func BeforeUpdate(strategy RESTUpdateStrategy, ctx context.Context, obj, old run
|
||||
|
||||
strategy.PrepareForUpdate(ctx, obj, old)
|
||||
|
||||
// ClusterName is ignored and should not be saved
|
||||
if len(objectMeta.GetClusterName()) > 0 {
|
||||
objectMeta.SetClusterName("")
|
||||
}
|
||||
// Use the existing UID if none is provided
|
||||
if len(objectMeta.GetUID()) == 0 {
|
||||
objectMeta.SetUID(oldMeta.GetUID())
|
||||
@@ -144,6 +164,10 @@ func BeforeUpdate(strategy RESTUpdateStrategy, ctx context.Context, obj, old run
|
||||
return errors.NewInvalid(kind.GroupKind(), objectMeta.GetName(), errs)
|
||||
}
|
||||
|
||||
for _, w := range strategy.WarningsOnUpdate(ctx, obj, old) {
|
||||
warning.AddWarning(ctx, "", w)
|
||||
}
|
||||
|
||||
strategy.Canonicalize(obj)
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user