1
16
17 package persistentvolumeclaim
18
19 import (
20 "fmt"
21 "reflect"
22 "testing"
23
24 "github.com/google/go-cmp/cmp"
25 genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
26 utilfeature "k8s.io/apiserver/pkg/util/feature"
27 featuregatetesting "k8s.io/component-base/featuregate/testing"
28 apitesting "k8s.io/kubernetes/pkg/api/testing"
29 api "k8s.io/kubernetes/pkg/apis/core"
30 "k8s.io/kubernetes/pkg/features"
31
32
33 _ "k8s.io/kubernetes/pkg/apis/core/install"
34 )
35
36 func TestSelectableFieldLabelConversions(t *testing.T) {
37 apitesting.TestSelectableFieldLabelConversionsOfKind(t,
38 "v1",
39 "PersistentVolumeClaim",
40 PersistentVolumeClaimToSelectableFields(&api.PersistentVolumeClaim{}),
41 map[string]string{"name": "metadata.name"},
42 )
43 }
44
45 func TestDropConditions(t *testing.T) {
46 ctx := genericapirequest.NewDefaultContext()
47 pvcWithConditions := func() *api.PersistentVolumeClaim {
48 return &api.PersistentVolumeClaim{
49 Status: api.PersistentVolumeClaimStatus{
50 Conditions: []api.PersistentVolumeClaimCondition{
51 {Type: api.PersistentVolumeClaimResizing, Status: api.ConditionTrue},
52 },
53 },
54 }
55 }
56 pvcWithoutConditions := func() *api.PersistentVolumeClaim {
57 return &api.PersistentVolumeClaim{
58 Status: api.PersistentVolumeClaimStatus{},
59 }
60 }
61
62 pvcInfo := []struct {
63 description string
64 hasConditions bool
65 pvc func() *api.PersistentVolumeClaim
66 }{
67 {
68 description: "has Conditions",
69 hasConditions: true,
70 pvc: pvcWithConditions,
71 },
72 {
73 description: "does not have Conditions",
74 hasConditions: false,
75 pvc: pvcWithoutConditions,
76 },
77 }
78
79 for _, oldPvcInfo := range pvcInfo {
80 for _, newPvcInfo := range pvcInfo {
81 oldPvcHasConditins, oldPvc := oldPvcInfo.hasConditions, oldPvcInfo.pvc()
82 newPvcHasConditions, newPvc := newPvcInfo.hasConditions, newPvcInfo.pvc()
83
84 t.Run(fmt.Sprintf("old pvc %s, new pvc %s", oldPvcInfo.description, newPvcInfo.description), func(t *testing.T) {
85 StatusStrategy.PrepareForUpdate(ctx, newPvc, oldPvc)
86
87
88 if !reflect.DeepEqual(oldPvc, oldPvcInfo.pvc()) {
89 t.Errorf("old pvc changed: %v", cmp.Diff(oldPvc, oldPvcInfo.pvc()))
90 }
91
92 switch {
93 case oldPvcHasConditins || newPvcHasConditions:
94
95 if !reflect.DeepEqual(newPvc, newPvcInfo.pvc()) {
96 t.Errorf("new pvc changed: %v", cmp.Diff(newPvc, newPvcInfo.pvc()))
97 }
98 default:
99
100 if !reflect.DeepEqual(newPvc, newPvcInfo.pvc()) {
101 t.Errorf("new pvc changed: %v", cmp.Diff(newPvc, newPvcInfo.pvc()))
102 }
103 }
104 })
105 }
106 }
107
108 }
109
110 var (
111 coreGroup = ""
112 snapGroup = "snapshot.storage.k8s.io"
113 genericGroup = "generic.storage.k8s.io"
114 pvcKind = "PersistentVolumeClaim"
115 snapKind = "VolumeSnapshot"
116 genericKind = "Generic"
117 podKind = "Pod"
118 )
119
120 func makeDataSource(apiGroup, kind, name string) *api.TypedLocalObjectReference {
121 return &api.TypedLocalObjectReference{
122 APIGroup: &apiGroup,
123 Kind: kind,
124 Name: name,
125 }
126
127 }
128
129 func makeDataSourceRef(apiGroup, kind, name string, namespace *string) *api.TypedObjectReference {
130 return &api.TypedObjectReference{
131 APIGroup: &apiGroup,
132 Kind: kind,
133 Name: name,
134 Namespace: namespace,
135 }
136 }
137
138 func TestPrepareForCreate(t *testing.T) {
139 ctx := genericapirequest.NewDefaultContext()
140
141 ns := "ns1"
142 volumeDataSource := makeDataSource(coreGroup, pvcKind, "my-vol")
143 volumeDataSourceRef := makeDataSourceRef(coreGroup, pvcKind, "my-vol", nil)
144 xnsVolumeDataSourceRef := makeDataSourceRef(coreGroup, pvcKind, "my-vol", &ns)
145 snapshotDataSource := makeDataSource(snapGroup, snapKind, "my-snap")
146 snapshotDataSourceRef := makeDataSourceRef(snapGroup, snapKind, "my-snap", nil)
147 xnsSnapshotDataSourceRef := makeDataSourceRef(snapGroup, snapKind, "my-snap", &ns)
148 genericDataSource := makeDataSource(genericGroup, genericKind, "my-foo")
149 genericDataSourceRef := makeDataSourceRef(genericGroup, genericKind, "my-foo", nil)
150 xnsGenericDataSourceRef := makeDataSourceRef(genericGroup, genericKind, "my-foo", &ns)
151 coreDataSource := makeDataSource(coreGroup, podKind, "my-pod")
152 coreDataSourceRef := makeDataSourceRef(coreGroup, podKind, "my-pod", nil)
153 xnsCoreDataSourceRef := makeDataSourceRef(coreGroup, podKind, "my-pod", &ns)
154
155 var tests = map[string]struct {
156 anyEnabled bool
157 xnsEnabled bool
158 dataSource *api.TypedLocalObjectReference
159 dataSourceRef *api.TypedObjectReference
160 want *api.TypedLocalObjectReference
161 wantRef *api.TypedObjectReference
162 }{
163 "any disabled with empty ds": {
164 want: nil,
165 },
166 "any disabled with volume ds": {
167 dataSource: volumeDataSource,
168 want: volumeDataSource,
169 },
170 "any disabled with snapshot ds": {
171 dataSource: snapshotDataSource,
172 want: snapshotDataSource,
173 },
174 "any disabled with generic ds": {
175 dataSource: genericDataSource,
176 want: nil,
177 },
178 "any disabled with invalid ds": {
179 dataSource: coreDataSource,
180 want: nil,
181 },
182 "any disabled with volume ds ref": {
183 dataSourceRef: volumeDataSourceRef,
184 },
185 "any disabled with snapshot ds ref": {
186 dataSourceRef: snapshotDataSourceRef,
187 },
188 "any disabled with generic ds ref": {
189 dataSourceRef: genericDataSourceRef,
190 },
191 "any disabled with invalid ds ref": {
192 dataSourceRef: coreDataSourceRef,
193 },
194 "any enabled with empty ds": {
195 anyEnabled: true,
196 want: nil,
197 },
198 "any enabled with volume ds": {
199 dataSource: volumeDataSource,
200 anyEnabled: true,
201 want: volumeDataSource,
202 wantRef: volumeDataSourceRef,
203 },
204 "any enabled with snapshot ds": {
205 dataSource: snapshotDataSource,
206 anyEnabled: true,
207 want: snapshotDataSource,
208 wantRef: snapshotDataSourceRef,
209 },
210 "any enabled with generic ds": {
211 dataSource: genericDataSource,
212 anyEnabled: true,
213 },
214 "any enabled with invalid ds": {
215 dataSource: coreDataSource,
216 anyEnabled: true,
217 },
218 "any enabled with volume ds ref": {
219 dataSourceRef: volumeDataSourceRef,
220 anyEnabled: true,
221 want: volumeDataSource,
222 wantRef: volumeDataSourceRef,
223 },
224 "any enabled with snapshot ds ref": {
225 dataSourceRef: snapshotDataSourceRef,
226 anyEnabled: true,
227 want: snapshotDataSource,
228 wantRef: snapshotDataSourceRef,
229 },
230 "any enabled with generic ds ref": {
231 dataSourceRef: genericDataSourceRef,
232 anyEnabled: true,
233 want: genericDataSource,
234 wantRef: genericDataSourceRef,
235 },
236 "any enabled with invalid ds ref": {
237 dataSourceRef: coreDataSourceRef,
238 anyEnabled: true,
239 want: coreDataSource,
240 wantRef: coreDataSourceRef,
241 },
242 "any enabled with mismatched data sources": {
243 dataSource: volumeDataSource,
244 dataSourceRef: snapshotDataSourceRef,
245 anyEnabled: true,
246 want: volumeDataSource,
247 wantRef: snapshotDataSourceRef,
248 },
249 "both any and xns enabled with empty ds": {
250 anyEnabled: true,
251 xnsEnabled: true,
252 want: nil,
253 },
254 "both any and xns enabled with volume ds": {
255 dataSource: volumeDataSource,
256 anyEnabled: true,
257 xnsEnabled: true,
258 want: volumeDataSource,
259 wantRef: volumeDataSourceRef,
260 },
261 "both any and xns enabled with snapshot ds": {
262 dataSource: snapshotDataSource,
263 anyEnabled: true,
264 xnsEnabled: true,
265 want: snapshotDataSource,
266 wantRef: snapshotDataSourceRef,
267 },
268 "both any and xns enabled with generic ds": {
269 dataSource: genericDataSource,
270 anyEnabled: true,
271 xnsEnabled: true,
272 },
273 "both any and xns enabled with invalid ds": {
274 dataSource: coreDataSource,
275 anyEnabled: true,
276 xnsEnabled: true,
277 },
278 "both any and xns enabled with volume ds ref": {
279 dataSourceRef: volumeDataSourceRef,
280 anyEnabled: true,
281 xnsEnabled: true,
282 want: volumeDataSource,
283 wantRef: volumeDataSourceRef,
284 },
285 "both any and xns enabled with snapshot ds ref": {
286 dataSourceRef: snapshotDataSourceRef,
287 anyEnabled: true,
288 xnsEnabled: true,
289 want: snapshotDataSource,
290 wantRef: snapshotDataSourceRef,
291 },
292 "both any and xns enabled with generic ds ref": {
293 dataSourceRef: genericDataSourceRef,
294 anyEnabled: true,
295 xnsEnabled: true,
296 want: genericDataSource,
297 wantRef: genericDataSourceRef,
298 },
299 "both any and xns enabled with invalid ds ref": {
300 dataSourceRef: coreDataSourceRef,
301 anyEnabled: true,
302 xnsEnabled: true,
303 want: coreDataSource,
304 wantRef: coreDataSourceRef,
305 },
306 "both any and xns enabled with mismatched data sources": {
307 dataSource: volumeDataSource,
308 dataSourceRef: snapshotDataSourceRef,
309 anyEnabled: true,
310 xnsEnabled: true,
311 want: volumeDataSource,
312 wantRef: snapshotDataSourceRef,
313 },
314 "both any and xns enabled with volume xns ds ref": {
315 dataSourceRef: xnsVolumeDataSourceRef,
316 anyEnabled: true,
317 xnsEnabled: true,
318 wantRef: xnsVolumeDataSourceRef,
319 },
320 "both any and xns enabled with snapshot xns ds ref": {
321 dataSourceRef: xnsSnapshotDataSourceRef,
322 anyEnabled: true,
323 xnsEnabled: true,
324 wantRef: xnsSnapshotDataSourceRef,
325 },
326 "both any and xns enabled with generic xns ds ref": {
327 dataSourceRef: xnsGenericDataSourceRef,
328 anyEnabled: true,
329 xnsEnabled: true,
330 wantRef: xnsGenericDataSourceRef,
331 },
332 "both any and xns enabled with invalid xns ds ref": {
333 dataSourceRef: xnsCoreDataSourceRef,
334 anyEnabled: true,
335 xnsEnabled: true,
336 wantRef: xnsCoreDataSourceRef,
337 },
338 "only xns enabled with snapshot xns ds ref": {
339 dataSourceRef: xnsSnapshotDataSourceRef,
340 xnsEnabled: true,
341 },
342 }
343
344 for testName, test := range tests {
345 t.Run(testName, func(t *testing.T) {
346 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AnyVolumeDataSource, test.anyEnabled)()
347 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CrossNamespaceVolumeDataSource, test.xnsEnabled)()
348 pvc := api.PersistentVolumeClaim{
349 Spec: api.PersistentVolumeClaimSpec{
350 DataSource: test.dataSource,
351 DataSourceRef: test.dataSourceRef,
352 },
353 }
354
355
356 Strategy.PrepareForCreate(ctx, &pvc)
357
358 if !reflect.DeepEqual(pvc.Spec.DataSource, test.want) {
359 t.Errorf("data source does not match, test: %s, anyEnabled: %v, dataSource: %v, expected: %v",
360 testName, test.anyEnabled, test.dataSource, test.want)
361 }
362 if !reflect.DeepEqual(pvc.Spec.DataSourceRef, test.wantRef) {
363 t.Errorf("data source ref does not match, test: %s, anyEnabled: %v, dataSourceRef: %v, expected: %v",
364 testName, test.anyEnabled, test.dataSourceRef, test.wantRef)
365 }
366 })
367 }
368 }
369
View as plain text