@@ -37,7 +37,7 @@ func TestController(t *testing.T) {
37
37
}{
38
38
{
39
39
name : "Modify called" ,
40
- pvc : createTestPVC (pvcName , "target-vac" /*vacName*/ , testVac /*curVacName*/ , testVac /*targetVacName*/ ),
40
+ pvc : createTestPVC (pvcName , targetVac /*vacName*/ , testVac /*curVacName*/ , testVac /*targetVacName*/ ),
41
41
pv : basePV ,
42
42
vacExists : true ,
43
43
callCSIModify : true ,
@@ -61,57 +61,13 @@ func TestController(t *testing.T) {
61
61
for _ , test := range tests {
62
62
t .Run (test .name , func (t * testing.T ) {
63
63
// Setup
64
- client := csi .NewMockClient ("foo" , true , true , true , true , true , false )
65
- driverName , _ := client .GetDriverName (context .TODO ())
66
-
67
- var initialObjects []runtime.Object
68
- initialObjects = append (initialObjects , test .pvc )
69
- initialObjects = append (initialObjects , test .pv )
70
- // existing vac set in the pvc and pv
71
- initialObjects = append (initialObjects , testVacObject )
72
- if test .vacExists {
73
- initialObjects = append (initialObjects , targetVacObject )
74
- }
75
-
76
- kubeClient , informerFactory := fakeK8s (initialObjects )
77
- pvInformer := informerFactory .Core ().V1 ().PersistentVolumes ()
78
- pvcInformer := informerFactory .Core ().V1 ().PersistentVolumeClaims ()
79
- vacInformer := informerFactory .Storage ().V1beta1 ().VolumeAttributesClasses ()
80
-
81
- csiModifier , err := modifier .NewModifierFromClient (client , 15 * time .Second , kubeClient , informerFactory , false , driverName )
82
- if err != nil {
83
- t .Fatalf ("Test %s: Unable to create modifier: %v" , test .name , err )
84
- }
85
-
86
- featuregatetesting .SetFeatureGateDuringTest (t , utilfeature .DefaultFeatureGate , features .VolumeAttributesClass , true )
87
- controller := NewModifyController (driverName ,
88
- csiModifier , kubeClient ,
89
- time .Second , false , informerFactory ,
90
- workqueue .DefaultTypedControllerRateLimiter [string ]())
64
+ client := csi .NewMockClient (testDriverName , true , true , true , true , true , false )
91
65
92
- ctrlInstance , _ := controller .(* modifyController )
93
-
94
- stopCh := make (chan struct {})
95
- informerFactory .Start (stopCh )
96
-
97
- ctx := context .TODO ()
66
+ initialObjects := []runtime.Object {test .pvc , test .pv , testVacObject , targetVacObject }
67
+ ctrlInstance , ctx := setupFakeK8sEnvironment (t , client , initialObjects )
98
68
defer ctx .Done ()
99
- go controller .Run (1 , ctx )
100
-
101
- for _ , obj := range initialObjects {
102
- switch obj .(type ) {
103
- case * v1.PersistentVolume :
104
- pvInformer .Informer ().GetStore ().Add (obj )
105
- case * v1.PersistentVolumeClaim :
106
- pvcInformer .Informer ().GetStore ().Add (obj )
107
- case * storagev1beta1.VolumeAttributesClass :
108
- vacInformer .Informer ().GetStore ().Add (obj )
109
- default :
110
- t .Fatalf ("Test %s: Unknown initalObject type: %+v" , test .name , obj )
111
- }
112
- }
113
- time .Sleep (time .Second * 2 )
114
- _ , _ , err , _ = ctrlInstance .modify (test .pvc , test .pv )
69
+
70
+ _ , _ , err , _ := ctrlInstance .modify (test .pvc , test .pv )
115
71
if err != nil {
116
72
t .Fatalf ("for %s: unexpected error: %v" , test .name , err )
117
73
}
@@ -141,14 +97,14 @@ func TestModifyPVC(t *testing.T) {
141
97
}{
142
98
{
143
99
name : "Modify succeeded" ,
144
- pvc : createTestPVC (pvcName , "target-vac" /*vacName*/ , testVac /*curVacName*/ , testVac /*targetVacName*/ ),
100
+ pvc : createTestPVC (pvcName , targetVac /*vacName*/ , testVac /*curVacName*/ , testVac /*targetVacName*/ ),
145
101
pv : basePV ,
146
102
modifyFailure : false ,
147
103
expectFailure : false ,
148
104
},
149
105
{
150
106
name : "Modify failed" ,
151
- pvc : createTestPVC (pvcName , "target-vac" /*vacName*/ , testVac /*curVacName*/ , testVac /*targetVacName*/ ),
107
+ pvc : createTestPVC (pvcName , targetVac /*vacName*/ , testVac /*curVacName*/ , testVac /*targetVacName*/ ),
152
108
pv : basePV ,
153
109
modifyFailure : true ,
154
110
expectFailure : true ,
@@ -157,77 +113,152 @@ func TestModifyPVC(t *testing.T) {
157
113
158
114
for _ , test := range tests {
159
115
t .Run (test .name , func (t * testing.T ) {
160
- client := csi .NewMockClient ("mock" , true , true , true , true , true , false )
116
+ client := csi .NewMockClient (testDriverName , true , true , true , true , true , false )
161
117
if test .modifyFailure {
162
118
client .SetModifyFailed ()
163
119
}
164
- driverName , _ := client .GetDriverName (context .TODO ())
165
120
166
- initialObjects := []runtime.Object {}
167
- if test .pvc != nil {
168
- initialObjects = append (initialObjects , test .pvc )
121
+ initialObjects := []runtime.Object {test .pvc , test .pv , testVacObject , targetVacObject }
122
+ ctrlInstance , ctx := setupFakeK8sEnvironment (t , client , initialObjects )
123
+ defer ctx .Done ()
124
+
125
+ _ , _ , err , _ := ctrlInstance .modify (test .pvc , test .pv )
126
+
127
+ if test .expectFailure && err == nil {
128
+ t .Errorf ("for %s expected error got nothing" , test .name )
169
129
}
170
- if test .pv != nil {
171
- test .pv .Spec .PersistentVolumeSource .CSI .Driver = driverName
172
- initialObjects = append (initialObjects , test .pv )
130
+
131
+ if ! test .expectFailure {
132
+ if err != nil {
133
+ t .Errorf ("for %s, unexpected error: %v" , test .name , err )
134
+ }
173
135
}
136
+ })
137
+ }
138
+ }
174
139
175
- // existing vac set in the pvc and pv
176
- initialObjects = append (initialObjects , testVacObject )
177
- // new vac used in modify volume
178
- initialObjects = append (initialObjects , targetVacObject )
140
+ func TestSyncPVC (t * testing.T ) {
141
+ basePVC := createTestPVC (pvcName , targetVac /*vacName*/ , testVac /*curVacName*/ , testVac /*targetVacName*/ )
142
+ basePV := createTestPV (1 , pvcName , pvcNamespace , "foobaz" /*pvcUID*/ , & fsVolumeMode , testVac )
179
143
180
- kubeClient , informerFactory := fakeK8s (initialObjects )
181
- pvInformer := informerFactory .Core ().V1 ().PersistentVolumes ()
182
- pvcInformer := informerFactory .Core ().V1 ().PersistentVolumeClaims ()
183
- vacInformer := informerFactory .Storage ().V1beta1 ().VolumeAttributesClasses ()
144
+ otherDriverPV := createTestPV (1 , pvcName , pvcNamespace , "foobaz" /*pvcUID*/ , & fsVolumeMode , testVac )
145
+ otherDriverPV .Spec .PersistentVolumeSource .CSI .Driver = "some-other-driver"
184
146
185
- csiModifier , err := modifier .NewModifierFromClient (client , 15 * time .Second , kubeClient , informerFactory , false , driverName )
186
- if err != nil {
187
- t .Fatalf ("Test %s: Unable to create modifier: %v" , test .name , err )
188
- }
147
+ unboundPVC := createTestPVC (pvcName , targetVac /*vacName*/ , testVac /*curVacName*/ , testVac /*targetVacName*/ )
148
+ unboundPVC .Status .Phase = v1 .ClaimPending
189
149
190
- featuregatetesting .SetFeatureGateDuringTest (t , utilfeature .DefaultFeatureGate , features .VolumeAttributesClass , true )
191
- controller := NewModifyController (driverName ,
192
- csiModifier , kubeClient ,
193
- time .Second , false , informerFactory ,
194
- workqueue .DefaultTypedControllerRateLimiter [string ]())
150
+ pvcWithUncreatedPV := createTestPVC (pvcName , targetVac /*vacName*/ , testVac /*curVacName*/ , testVac /*targetVacName*/ )
151
+ pvcWithUncreatedPV .Spec .VolumeName = ""
195
152
196
- ctrlInstance , _ := controller .(* modifyController )
153
+ tests := []struct {
154
+ name string
155
+ pvc * v1.PersistentVolumeClaim
156
+ pv * v1.PersistentVolume
157
+ callCSIModify bool
158
+ }{
159
+ {
160
+ name : "Should execute ModifyVolume operation when PVC's VAC changes" ,
161
+ pvc : basePVC ,
162
+ pv : basePV ,
163
+ callCSIModify : true ,
164
+ },
165
+ {
166
+ name : "Should NOT modify if PVC managed by another CSI Driver" ,
167
+ pvc : basePVC ,
168
+ pv : otherDriverPV ,
169
+ callCSIModify : false ,
170
+ },
171
+ {
172
+ name : "Should NOT modify if PVC has empty Spec.VACName" ,
173
+ pvc : createTestPVC (pvcName , "" /*vacName*/ , testVac /*curVacName*/ , testVac /*targetVacName*/ ),
174
+ pv : basePV ,
175
+ callCSIModify : false ,
176
+ },
177
+ {
178
+ name : "Should NOT modify if PVC not in bound state" ,
179
+ pvc : unboundPVC ,
180
+ pv : basePV ,
181
+ callCSIModify : false ,
182
+ },
183
+ {
184
+ name : "Should NOT modify if PVC's PV not created yet" ,
185
+ pvc : pvcWithUncreatedPV ,
186
+ pv : basePV ,
187
+ callCSIModify : false ,
188
+ },
189
+ }
197
190
198
- stopCh := make (chan struct {})
199
- informerFactory .Start (stopCh )
191
+ for _ , test := range tests {
192
+ t .Run (test .name , func (t * testing.T ) {
193
+ client := csi .NewMockClient (testDriverName , true , true , true , true , true , false )
200
194
201
- ctx := context .TODO ()
195
+ initialObjects := []runtime.Object {test .pvc , test .pv , testVacObject , targetVacObject }
196
+ ctrlInstance , ctx := setupFakeK8sEnvironment (t , client , initialObjects )
202
197
defer ctx .Done ()
203
- go controller .Run (1 , ctx )
204
-
205
- for _ , obj := range initialObjects {
206
- switch obj .(type ) {
207
- case * v1.PersistentVolume :
208
- pvInformer .Informer ().GetStore ().Add (obj )
209
- case * v1.PersistentVolumeClaim :
210
- pvcInformer .Informer ().GetStore ().Add (obj )
211
- case * storagev1beta1.VolumeAttributesClass :
212
- vacInformer .Informer ().GetStore ().Add (obj )
213
- default :
214
- t .Fatalf ("Test %s: Unknown initalObject type: %+v" , test .name , obj )
215
- }
216
- }
217
-
218
- time .Sleep (time .Second * 2 )
219
198
220
- _ , _ , err , _ = ctrlInstance .modify (test .pvc , test .pv )
199
+ err := ctrlInstance .syncPVC (pvcNamespace + "/" + pvcName )
200
+ if err != nil {
201
+ t .Errorf ("for %s, unexpected error: %v" , test .name , err )
202
+ }
221
203
222
- if test .expectFailure && err == nil {
223
- t .Errorf ("for %s expected error got nothing" , test .name )
204
+ modifyCallCount := client .GetModifyCount ()
205
+ if test .callCSIModify && modifyCallCount == 0 {
206
+ t .Fatalf ("for %s: expected csi modify call, no csi modify call was made" , test .name )
224
207
}
225
208
226
- if ! test .expectFailure {
227
- if err != nil {
228
- t .Errorf ("for %s, unexpected error: %v" , test .name , err )
229
- }
209
+ if ! test .callCSIModify && modifyCallCount > 0 {
210
+ t .Fatalf ("for %s: expected no csi modify call, received csi modify request" , test .name )
230
211
}
231
212
})
232
213
}
233
214
}
215
+
216
+ // setupFakeK8sEnvironment creates fake K8s environment and starts Informers and ModifyController
217
+ func setupFakeK8sEnvironment (t * testing.T , client * csi.MockClient , initialObjects []runtime.Object ) (* modifyController , context.Context ) {
218
+ t .Helper ()
219
+
220
+ featuregatetesting .SetFeatureGateDuringTest (t , utilfeature .DefaultFeatureGate , features .VolumeAttributesClass , true )
221
+
222
+ /* Create fake kubeClient, Informers, and ModifyController */
223
+ kubeClient , informerFactory := fakeK8s (initialObjects )
224
+ pvInformer := informerFactory .Core ().V1 ().PersistentVolumes ()
225
+ pvcInformer := informerFactory .Core ().V1 ().PersistentVolumeClaims ()
226
+ vacInformer := informerFactory .Storage ().V1beta1 ().VolumeAttributesClasses ()
227
+
228
+ driverName , _ := client .GetDriverName (context .TODO ())
229
+
230
+ csiModifier , err := modifier .NewModifierFromClient (client , 15 * time .Second , kubeClient , informerFactory , false , driverName )
231
+ if err != nil {
232
+ t .Fatalf ("Test %s: Unable to create modifier: %v" , t .Name (), err )
233
+ }
234
+
235
+ controller := NewModifyController (driverName ,
236
+ csiModifier , kubeClient ,
237
+ 0 , false , informerFactory ,
238
+ workqueue .DefaultTypedControllerRateLimiter [string ]())
239
+
240
+ /* Start informers and ModifyController*/
241
+ stopCh := make (chan struct {})
242
+ informerFactory .Start (stopCh )
243
+
244
+ ctx := context .TODO ()
245
+ go controller .Run (1 , ctx )
246
+
247
+ /* Add initial objects to informer caches */
248
+ for _ , obj := range initialObjects {
249
+ switch obj .(type ) {
250
+ case * v1.PersistentVolume :
251
+ pvInformer .Informer ().GetStore ().Add (obj )
252
+ case * v1.PersistentVolumeClaim :
253
+ pvcInformer .Informer ().GetStore ().Add (obj )
254
+ case * storagev1beta1.VolumeAttributesClass :
255
+ vacInformer .Informer ().GetStore ().Add (obj )
256
+ default :
257
+ t .Fatalf ("Test %s: Unknown initalObject type: %+v" , t .Name (), obj )
258
+ }
259
+ }
260
+
261
+ ctrlInstance , _ := controller .(* modifyController )
262
+
263
+ return ctrlInstance , ctx
264
+ }
0 commit comments