...

Source file src/k8s.io/kubernetes/pkg/registry/core/persistentvolume/strategy.go

Documentation: k8s.io/kubernetes/pkg/registry/core/persistentvolume

     1  /*
     2  Copyright 2014 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 persistentvolume
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	utilfeature "k8s.io/apiserver/pkg/util/feature"
    25  	"k8s.io/kubernetes/pkg/features"
    26  
    27  	"k8s.io/apimachinery/pkg/fields"
    28  	"k8s.io/apimachinery/pkg/labels"
    29  	"k8s.io/apimachinery/pkg/runtime"
    30  	"k8s.io/apimachinery/pkg/util/validation/field"
    31  	"k8s.io/apiserver/pkg/registry/generic"
    32  	"k8s.io/apiserver/pkg/storage"
    33  	"k8s.io/apiserver/pkg/storage/names"
    34  	"k8s.io/kubernetes/pkg/api/legacyscheme"
    35  	pvutil "k8s.io/kubernetes/pkg/api/persistentvolume"
    36  	api "k8s.io/kubernetes/pkg/apis/core"
    37  	"k8s.io/kubernetes/pkg/apis/core/validation"
    38  	volumevalidation "k8s.io/kubernetes/pkg/volume/validation"
    39  	"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
    40  )
    41  
    42  // persistentvolumeStrategy implements behavior for PersistentVolume objects
    43  type persistentvolumeStrategy struct {
    44  	runtime.ObjectTyper
    45  	names.NameGenerator
    46  }
    47  
    48  // Strategy is the default logic that applies when creating and updating PersistentVolume
    49  // objects via the REST API.
    50  var Strategy = persistentvolumeStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
    51  
    52  func (persistentvolumeStrategy) NamespaceScoped() bool {
    53  	return false
    54  }
    55  
    56  // GetResetFields returns the set of fields that get reset by the strategy
    57  // and should not be modified by the user.
    58  func (persistentvolumeStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
    59  	fields := map[fieldpath.APIVersion]*fieldpath.Set{
    60  		"v1": fieldpath.NewSet(
    61  			fieldpath.MakePathOrDie("status"),
    62  		),
    63  	}
    64  
    65  	return fields
    66  }
    67  
    68  // ResetBeforeCreate clears the Status field which is not allowed to be set by end users on creation.
    69  func (persistentvolumeStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
    70  	pv := obj.(*api.PersistentVolume)
    71  	pv.Status = api.PersistentVolumeStatus{}
    72  
    73  	if utilfeature.DefaultFeatureGate.Enabled(features.PersistentVolumeLastPhaseTransitionTime) {
    74  		pv.Status.Phase = api.VolumePending
    75  		now := NowFunc()
    76  		pv.Status.LastPhaseTransitionTime = &now
    77  	}
    78  }
    79  
    80  func (persistentvolumeStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
    81  	persistentvolume := obj.(*api.PersistentVolume)
    82  	opts := validation.ValidationOptionsForPersistentVolume(persistentvolume, nil)
    83  	errorList := validation.ValidatePersistentVolume(persistentvolume, opts)
    84  	return append(errorList, volumevalidation.ValidatePersistentVolume(persistentvolume)...)
    85  }
    86  
    87  // WarningsOnCreate returns warnings for the creation of the given object.
    88  func (persistentvolumeStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
    89  	return pvutil.GetWarningsForPersistentVolume(obj.(*api.PersistentVolume))
    90  }
    91  
    92  // Canonicalize normalizes the object after validation.
    93  func (persistentvolumeStrategy) Canonicalize(obj runtime.Object) {
    94  }
    95  
    96  func (persistentvolumeStrategy) AllowCreateOnUpdate() bool {
    97  	return false
    98  }
    99  
   100  // PrepareForUpdate sets the Status fields which is not allowed to be set by an end user updating a PV
   101  func (persistentvolumeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
   102  	newPv := obj.(*api.PersistentVolume)
   103  	oldPv := old.(*api.PersistentVolume)
   104  	newPv.Status = oldPv.Status
   105  }
   106  
   107  func (persistentvolumeStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
   108  	newPv := obj.(*api.PersistentVolume)
   109  	oldPv := old.(*api.PersistentVolume)
   110  	opts := validation.ValidationOptionsForPersistentVolume(newPv, oldPv)
   111  	errorList := validation.ValidatePersistentVolume(newPv, opts)
   112  	errorList = append(errorList, volumevalidation.ValidatePersistentVolume(newPv)...)
   113  	return append(errorList, validation.ValidatePersistentVolumeUpdate(newPv, oldPv, opts)...)
   114  }
   115  
   116  // WarningsOnUpdate returns warnings for the given update.
   117  func (persistentvolumeStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
   118  	return pvutil.GetWarningsForPersistentVolume(obj.(*api.PersistentVolume))
   119  }
   120  
   121  func (persistentvolumeStrategy) AllowUnconditionalUpdate() bool {
   122  	return true
   123  }
   124  
   125  type persistentvolumeStatusStrategy struct {
   126  	persistentvolumeStrategy
   127  }
   128  
   129  var StatusStrategy = persistentvolumeStatusStrategy{Strategy}
   130  
   131  // GetResetFields returns the set of fields that get reset by the strategy
   132  // and should not be modified by the user.
   133  func (persistentvolumeStatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
   134  	fields := map[fieldpath.APIVersion]*fieldpath.Set{
   135  		"v1": fieldpath.NewSet(
   136  			fieldpath.MakePathOrDie("spec"),
   137  		),
   138  	}
   139  
   140  	return fields
   141  }
   142  
   143  var NowFunc = metav1.Now
   144  
   145  // PrepareForUpdate sets the Spec field which is not allowed to be changed when updating a PV's Status
   146  func (persistentvolumeStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
   147  	newPv := obj.(*api.PersistentVolume)
   148  	oldPv := old.(*api.PersistentVolume)
   149  	newPv.Spec = oldPv.Spec
   150  
   151  	if utilfeature.DefaultFeatureGate.Enabled(features.PersistentVolumeLastPhaseTransitionTime) {
   152  		switch {
   153  		case oldPv.Status.Phase == newPv.Status.Phase && newPv.Status.LastPhaseTransitionTime == nil:
   154  			// phase didn't change, preserve the existing transition time if set
   155  			newPv.Status.LastPhaseTransitionTime = oldPv.Status.LastPhaseTransitionTime
   156  
   157  		case oldPv.Status.Phase != newPv.Status.Phase && (newPv.Status.LastPhaseTransitionTime == nil || newPv.Status.LastPhaseTransitionTime.Equal(oldPv.Status.LastPhaseTransitionTime)):
   158  			// phase changed and client didn't set or didn't change the transition time
   159  			now := NowFunc()
   160  			newPv.Status.LastPhaseTransitionTime = &now
   161  		}
   162  	}
   163  
   164  	pvutil.DropDisabledStatusFields(&oldPv.Status, &newPv.Status)
   165  }
   166  
   167  func (persistentvolumeStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
   168  	return validation.ValidatePersistentVolumeStatusUpdate(obj.(*api.PersistentVolume), old.(*api.PersistentVolume))
   169  }
   170  
   171  // WarningsOnUpdate returns warnings for the given update.
   172  func (persistentvolumeStatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
   173  	return nil
   174  }
   175  
   176  // GetAttrs returns labels and fields of a given object for filtering purposes.
   177  func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
   178  	persistentvolumeObj, ok := obj.(*api.PersistentVolume)
   179  	if !ok {
   180  		return nil, nil, fmt.Errorf("not a persistentvolume")
   181  	}
   182  	return labels.Set(persistentvolumeObj.Labels), PersistentVolumeToSelectableFields(persistentvolumeObj), nil
   183  }
   184  
   185  // MatchPersistentVolume returns a generic matcher for a given label and field selector.
   186  func MatchPersistentVolumes(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
   187  	return storage.SelectionPredicate{
   188  		Label:    label,
   189  		Field:    field,
   190  		GetAttrs: GetAttrs,
   191  	}
   192  }
   193  
   194  // PersistentVolumeToSelectableFields returns a field set that represents the object
   195  func PersistentVolumeToSelectableFields(persistentvolume *api.PersistentVolume) fields.Set {
   196  	objectMetaFieldsSet := generic.ObjectMetaFieldsSet(&persistentvolume.ObjectMeta, false)
   197  	specificFieldsSet := fields.Set{
   198  		// This is a bug, but we need to support it for backward compatibility.
   199  		"name": persistentvolume.Name,
   200  	}
   201  	return generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet)
   202  }
   203  

View as plain text