1
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
43 type persistentvolumeStrategy struct {
44 runtime.ObjectTyper
45 names.NameGenerator
46 }
47
48
49
50 var Strategy = persistentvolumeStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
51
52 func (persistentvolumeStrategy) NamespaceScoped() bool {
53 return false
54 }
55
56
57
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
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
88 func (persistentvolumeStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
89 return pvutil.GetWarningsForPersistentVolume(obj.(*api.PersistentVolume))
90 }
91
92
93 func (persistentvolumeStrategy) Canonicalize(obj runtime.Object) {
94 }
95
96 func (persistentvolumeStrategy) AllowCreateOnUpdate() bool {
97 return false
98 }
99
100
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
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
132
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
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
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
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
172 func (persistentvolumeStatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
173 return nil
174 }
175
176
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
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
195 func PersistentVolumeToSelectableFields(persistentvolume *api.PersistentVolume) fields.Set {
196 objectMetaFieldsSet := generic.ObjectMetaFieldsSet(&persistentvolume.ObjectMeta, false)
197 specificFieldsSet := fields.Set{
198
199 "name": persistentvolume.Name,
200 }
201 return generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet)
202 }
203
View as plain text