k8s.io/kubernetes@v1.29.3/pkg/registry/core/persistentvolumeclaim/storage/storage.go (about)

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package storage
    18  
    19  import (
    20  	"context"
    21  	pvcutil "k8s.io/kubernetes/pkg/api/persistentvolumeclaim"
    22  
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	"k8s.io/apimachinery/pkg/runtime"
    25  	"k8s.io/apiserver/pkg/registry/generic"
    26  	genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
    27  	"k8s.io/apiserver/pkg/registry/rest"
    28  	api "k8s.io/kubernetes/pkg/apis/core"
    29  	"k8s.io/kubernetes/pkg/printers"
    30  	printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
    31  	printerstorage "k8s.io/kubernetes/pkg/printers/storage"
    32  	"k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim"
    33  	"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
    34  )
    35  
    36  // REST implements a RESTStorage for persistent volume claims.
    37  type REST struct {
    38  	*genericregistry.Store
    39  }
    40  
    41  // NewREST returns a RESTStorage object that will work against persistent volume claims.
    42  func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
    43  	store := &genericregistry.Store{
    44  		NewFunc:                   func() runtime.Object { return &api.PersistentVolumeClaim{} },
    45  		NewListFunc:               func() runtime.Object { return &api.PersistentVolumeClaimList{} },
    46  		PredicateFunc:             persistentvolumeclaim.MatchPersistentVolumeClaim,
    47  		DefaultQualifiedResource:  api.Resource("persistentvolumeclaims"),
    48  		SingularQualifiedResource: api.Resource("persistentvolumeclaim"),
    49  
    50  		CreateStrategy:      persistentvolumeclaim.Strategy,
    51  		UpdateStrategy:      persistentvolumeclaim.Strategy,
    52  		DeleteStrategy:      persistentvolumeclaim.Strategy,
    53  		ReturnDeletedObject: true,
    54  		ResetFieldsStrategy: persistentvolumeclaim.Strategy,
    55  
    56  		TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
    57  	}
    58  	options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: persistentvolumeclaim.GetAttrs}
    59  	if err := store.CompleteWithOptions(options); err != nil {
    60  		return nil, nil, err
    61  	}
    62  
    63  	statusStore := *store
    64  	statusStore.UpdateStrategy = persistentvolumeclaim.StatusStrategy
    65  	statusStore.ResetFieldsStrategy = persistentvolumeclaim.StatusStrategy
    66  
    67  	rest := &REST{store}
    68  	store.Decorator = rest.defaultOnRead
    69  
    70  	return rest, &StatusREST{store: &statusStore}, nil
    71  }
    72  
    73  // Implement ShortNamesProvider
    74  var _ rest.ShortNamesProvider = &REST{}
    75  
    76  // ShortNames implements the ShortNamesProvider interface. Returns a list of short names for a resource.
    77  func (r *REST) ShortNames() []string {
    78  	return []string{"pvc"}
    79  }
    80  
    81  // defaultOnRead sets interlinked fields that were not previously set on read.
    82  // We can't do this in the normal defaulting path because that same logic
    83  // applies on Get, Create, and Update, but we need to distinguish between them.
    84  //
    85  // This will be called on both PersistentVolumeClaim and PersistentVolumeClaimList types.
    86  func (r *REST) defaultOnRead(obj runtime.Object) {
    87  	switch s := obj.(type) {
    88  	case *api.PersistentVolumeClaim:
    89  		r.defaultOnReadPvc(s)
    90  	case *api.PersistentVolumeClaimList:
    91  		r.defaultOnReadPvcList(s)
    92  	default:
    93  		// This was not an object we can default.  This is not an error, as the
    94  		// caching layer can pass through here, too.
    95  	}
    96  }
    97  
    98  // defaultOnReadPvcList defaults a PersistentVolumeClaimList.
    99  func (r *REST) defaultOnReadPvcList(pvcList *api.PersistentVolumeClaimList) {
   100  	if pvcList == nil {
   101  		return
   102  	}
   103  
   104  	for i := range pvcList.Items {
   105  		r.defaultOnReadPvc(&pvcList.Items[i])
   106  	}
   107  }
   108  
   109  // defaultOnReadPvc defaults a single PersistentVolumeClaim.
   110  func (r *REST) defaultOnReadPvc(pvc *api.PersistentVolumeClaim) {
   111  	if pvc == nil {
   112  		return
   113  	}
   114  
   115  	// We set dataSourceRef to the same value as dataSource at creation time now,
   116  	// but for pre-existing PVCs with data sources, the dataSourceRef field will
   117  	// be blank, so we fill it in here at read time.
   118  	pvcutil.NormalizeDataSources(&pvc.Spec)
   119  }
   120  
   121  // StatusREST implements the REST endpoint for changing the status of a persistentvolumeclaim.
   122  type StatusREST struct {
   123  	store *genericregistry.Store
   124  }
   125  
   126  // New creates a new PersistentVolumeClaim object.
   127  func (r *StatusREST) New() runtime.Object {
   128  	return &api.PersistentVolumeClaim{}
   129  }
   130  
   131  // Destroy cleans up resources on shutdown.
   132  func (r *StatusREST) Destroy() {
   133  	// Given that underlying store is shared with REST,
   134  	// we don't destroy it here explicitly.
   135  }
   136  
   137  // Get retrieves the object from the storage. It is required to support Patch.
   138  func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
   139  	return r.store.Get(ctx, name, options)
   140  }
   141  
   142  // Update alters the status subset of an object.
   143  func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
   144  	// We are explicitly setting forceAllowCreate to false in the call to the underlying storage because
   145  	// subresources should never allow create on update.
   146  	return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options)
   147  }
   148  
   149  // GetResetFields implements rest.ResetFieldsStrategy
   150  func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
   151  	return r.store.GetResetFields()
   152  }
   153  
   154  func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
   155  	return r.store.ConvertToTable(ctx, object, tableOptions)
   156  }