@@ -17,16 +17,25 @@ limitations under the License.
17
17
package storage
18
18
19
19
import (
20
+ "context"
20
21
"testing"
21
22
22
23
policyv1beta1 "k8s.io/api/policy/v1beta1"
24
+ "k8s.io/apimachinery/pkg/api/apitesting"
23
25
apierrors "k8s.io/apimachinery/pkg/api/errors"
24
26
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25
27
"k8s.io/apimachinery/pkg/runtime"
28
+ "k8s.io/apimachinery/pkg/runtime/serializer"
29
+ examplev1 "k8s.io/apiserver/pkg/apis/example/v1"
26
30
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
31
+ "k8s.io/apiserver/pkg/registry/generic"
32
+ genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
33
+ "k8s.io/apiserver/pkg/storage"
34
+ etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
27
35
"k8s.io/client-go/kubernetes/fake"
28
36
api "k8s.io/kubernetes/pkg/apis/core"
29
37
"k8s.io/kubernetes/pkg/apis/policy"
38
+ "k8s.io/kubernetes/pkg/registry/registrytest"
30
39
)
31
40
32
41
func TestEviction (t * testing.T ) {
@@ -136,3 +145,119 @@ func TestEviction(t *testing.T) {
136
145
})
137
146
}
138
147
}
148
+
149
+ type FailDeleteUpdateStorage struct {
150
+ storage.Interface
151
+ }
152
+
153
+ func (f FailDeleteUpdateStorage ) Delete (ctx context.Context , key string , out runtime.Object , precondition * storage.Preconditions ) error {
154
+ return storage .NewKeyNotFoundError (key , 0 )
155
+ }
156
+
157
+ func (f FailDeleteUpdateStorage ) GuaranteedUpdate (ctx context.Context , key string , ptrToType runtime.Object , ignoreNotFound bool ,
158
+ preconditions * storage.Preconditions , tryUpdate storage.UpdateFunc , suggestion ... runtime.Object ) error {
159
+ return storage .NewKeyNotFoundError (key , 0 )
160
+ }
161
+
162
+ var scheme = runtime .NewScheme ()
163
+ var codecs = serializer .NewCodecFactory (scheme )
164
+
165
+ func newFailDeleteUpdateStorage (t * testing.T ) (* REST , * etcdtesting.EtcdTestServer ) {
166
+ etcdStorage , server := registrytest .NewEtcdStorage (t , "" )
167
+ restOptions := generic.RESTOptions {
168
+ StorageConfig : etcdStorage ,
169
+ Decorator : generic .UndecoratedStorage ,
170
+ DeleteCollectionWorkers : 3 ,
171
+ ResourcePrefix : "pods" ,
172
+ }
173
+ storage := NewStorage (restOptions , nil , nil , nil )
174
+ storage .Pod .Store .Storage = genericregistry.DryRunnableStorage {
175
+ Storage : FailDeleteUpdateStorage {storage .Pod .Store .Storage .Storage },
176
+ Codec : apitesting .TestStorageCodec (codecs , examplev1 .SchemeGroupVersion ),
177
+ }
178
+ return storage .Pod , server
179
+ }
180
+
181
+ func TestEvictionDryRun (t * testing.T ) {
182
+ testcases := []struct {
183
+ name string
184
+ evictionOptions * metav1.DeleteOptions
185
+ requestOptions * metav1.CreateOptions
186
+ pod * api.Pod
187
+ pdbs []runtime.Object
188
+ }{
189
+ {
190
+ name : "just request-options" ,
191
+ requestOptions : & metav1.CreateOptions {DryRun : []string {"All" }},
192
+ evictionOptions : & metav1.DeleteOptions {},
193
+ pod : func () * api.Pod {
194
+ pod := validNewPod ()
195
+ pod .Labels = map [string ]string {"a" : "true" }
196
+ pod .Spec .NodeName = "foo"
197
+ return pod
198
+ }(),
199
+ },
200
+ {
201
+ name : "just eviction-options" ,
202
+ requestOptions : & metav1.CreateOptions {},
203
+ evictionOptions : & metav1.DeleteOptions {DryRun : []string {"All" }},
204
+ pod : func () * api.Pod {
205
+ pod := validNewPod ()
206
+ pod .Labels = map [string ]string {"a" : "true" }
207
+ pod .Spec .NodeName = "foo"
208
+ return pod
209
+ }(),
210
+ },
211
+ {
212
+ name : "both options" ,
213
+ evictionOptions : & metav1.DeleteOptions {DryRun : []string {"All" }},
214
+ requestOptions : & metav1.CreateOptions {DryRun : []string {"All" }},
215
+ pod : func () * api.Pod {
216
+ pod := validNewPod ()
217
+ pod .Labels = map [string ]string {"a" : "true" }
218
+ pod .Spec .NodeName = "foo"
219
+ return pod
220
+ }(),
221
+ },
222
+ {
223
+ name : "with pdbs" ,
224
+ evictionOptions : & metav1.DeleteOptions {DryRun : []string {"All" }},
225
+ requestOptions : & metav1.CreateOptions {DryRun : []string {"All" }},
226
+ pod : func () * api.Pod {
227
+ pod := validNewPod ()
228
+ pod .Labels = map [string ]string {"a" : "true" }
229
+ pod .Spec .NodeName = "foo"
230
+ return pod
231
+ }(),
232
+ pdbs : []runtime.Object {& policyv1beta1.PodDisruptionBudget {
233
+ ObjectMeta : metav1.ObjectMeta {Name : "foo" , Namespace : "default" },
234
+ Spec : policyv1beta1.PodDisruptionBudgetSpec {Selector : & metav1.LabelSelector {MatchLabels : map [string ]string {"a" : "true" }}},
235
+ Status : policyv1beta1.PodDisruptionBudgetStatus {PodDisruptionsAllowed : 1 },
236
+ }},
237
+ },
238
+ }
239
+
240
+ for _ , tc := range testcases {
241
+ t .Run (tc .name , func (t * testing.T ) {
242
+ testContext := genericapirequest .WithNamespace (genericapirequest .NewContext (), metav1 .NamespaceDefault )
243
+ storage , server := newFailDeleteUpdateStorage (t )
244
+ defer server .Terminate (t )
245
+ defer storage .Store .DestroyFunc ()
246
+
247
+ pod := validNewPod ()
248
+ pod .Labels = map [string ]string {"a" : "true" }
249
+ pod .Spec .NodeName = "foo"
250
+ if _ , err := storage .Create (testContext , pod , nil , & metav1.CreateOptions {}); err != nil {
251
+ t .Error (err )
252
+ }
253
+
254
+ client := fake .NewSimpleClientset ()
255
+ evictionRest := newEvictionStorage (storage .Store , client .PolicyV1beta1 ())
256
+ eviction := & policy.Eviction {ObjectMeta : metav1.ObjectMeta {Name : "foo" , Namespace : "default" }, DeleteOptions : tc .evictionOptions }
257
+ _ , err := evictionRest .Create (testContext , eviction , nil , tc .requestOptions )
258
+ if err != nil {
259
+ t .Fatalf ("Failed to run eviction: %v" , err )
260
+ }
261
+ })
262
+ }
263
+ }
0 commit comments