volcano.sh/volcano@v1.9.0/pkg/scheduler/capabilities/volumebinding/assume_cache_test.go (about) 1 /* 2 Copyright 2017 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 volumebinding 18 19 import ( 20 "fmt" 21 "testing" 22 23 v1 "k8s.io/api/core/v1" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/component-helpers/storage/volume" 26 "k8s.io/klog/v2/ktesting" 27 ) 28 29 func verifyListPVs(t *testing.T, cache PVAssumeCache, expectedPVs map[string]*v1.PersistentVolume, storageClassName string) { 30 pvList := cache.ListPVs(storageClassName) 31 if len(pvList) != len(expectedPVs) { 32 t.Errorf("ListPVs() returned %v PVs, expected %v", len(pvList), len(expectedPVs)) 33 } 34 for _, pv := range pvList { 35 expectedPV, ok := expectedPVs[pv.Name] 36 if !ok { 37 t.Errorf("ListPVs() returned unexpected PV %q", pv.Name) 38 } 39 if expectedPV != pv { 40 t.Errorf("ListPVs() returned PV %p, expected %p", pv, expectedPV) 41 } 42 } 43 } 44 45 func verifyPV(cache PVAssumeCache, name string, expectedPV *v1.PersistentVolume) error { 46 pv, err := cache.GetPV(name) 47 if err != nil { 48 return err 49 } 50 if pv != expectedPV { 51 return fmt.Errorf("GetPV() returned %p, expected %p", pv, expectedPV) 52 } 53 return nil 54 } 55 56 func TestAssumePV(t *testing.T) { 57 logger, _ := ktesting.NewTestContext(t) 58 scenarios := map[string]struct { 59 oldPV *v1.PersistentVolume 60 newPV *v1.PersistentVolume 61 shouldSucceed bool 62 }{ 63 "success-same-version": { 64 oldPV: makePV("pv1", "").withVersion("5").PersistentVolume, 65 newPV: makePV("pv1", "").withVersion("5").PersistentVolume, 66 shouldSucceed: true, 67 }, 68 "success-storageclass-same-version": { 69 oldPV: makePV("pv1", "class1").withVersion("5").PersistentVolume, 70 newPV: makePV("pv1", "class1").withVersion("5").PersistentVolume, 71 shouldSucceed: true, 72 }, 73 "success-new-higher-version": { 74 oldPV: makePV("pv1", "").withVersion("5").PersistentVolume, 75 newPV: makePV("pv1", "").withVersion("6").PersistentVolume, 76 shouldSucceed: true, 77 }, 78 "fail-old-not-found": { 79 oldPV: makePV("pv2", "").withVersion("5").PersistentVolume, 80 newPV: makePV("pv1", "").withVersion("5").PersistentVolume, 81 shouldSucceed: false, 82 }, 83 "fail-new-lower-version": { 84 oldPV: makePV("pv1", "").withVersion("5").PersistentVolume, 85 newPV: makePV("pv1", "").withVersion("4").PersistentVolume, 86 shouldSucceed: false, 87 }, 88 "fail-new-bad-version": { 89 oldPV: makePV("pv1", "").withVersion("5").PersistentVolume, 90 newPV: makePV("pv1", "").withVersion("a").PersistentVolume, 91 shouldSucceed: false, 92 }, 93 "fail-old-bad-version": { 94 oldPV: makePV("pv1", "").withVersion("a").PersistentVolume, 95 newPV: makePV("pv1", "").withVersion("5").PersistentVolume, 96 shouldSucceed: false, 97 }, 98 } 99 100 for name, scenario := range scenarios { 101 cache := NewPVAssumeCache(logger, nil) 102 internalCache, ok := cache.(*pvAssumeCache).AssumeCache.(*assumeCache) 103 if !ok { 104 t.Fatalf("Failed to get internal cache") 105 } 106 107 // Add oldPV to cache 108 internalCache.add(scenario.oldPV) 109 if err := verifyPV(cache, scenario.oldPV.Name, scenario.oldPV); err != nil { 110 t.Errorf("Failed to GetPV() after initial update: %v", err) 111 continue 112 } 113 114 // Assume newPV 115 err := cache.Assume(scenario.newPV) 116 if scenario.shouldSucceed && err != nil { 117 t.Errorf("Test %q failed: Assume() returned error %v", name, err) 118 } 119 if !scenario.shouldSucceed && err == nil { 120 t.Errorf("Test %q failed: Assume() returned success but expected error", name) 121 } 122 123 // Check that GetPV returns correct PV 124 expectedPV := scenario.newPV 125 if !scenario.shouldSucceed { 126 expectedPV = scenario.oldPV 127 } 128 if err := verifyPV(cache, scenario.oldPV.Name, expectedPV); err != nil { 129 t.Errorf("Failed to GetPV() after initial update: %v", err) 130 } 131 } 132 } 133 134 func TestRestorePV(t *testing.T) { 135 logger, _ := ktesting.NewTestContext(t) 136 cache := NewPVAssumeCache(logger, nil) 137 internalCache, ok := cache.(*pvAssumeCache).AssumeCache.(*assumeCache) 138 if !ok { 139 t.Fatalf("Failed to get internal cache") 140 } 141 142 oldPV := makePV("pv1", "").withVersion("5").PersistentVolume 143 newPV := makePV("pv1", "").withVersion("5").PersistentVolume 144 145 // Restore PV that doesn't exist 146 cache.Restore("nothing") 147 148 // Add oldPV to cache 149 internalCache.add(oldPV) 150 if err := verifyPV(cache, oldPV.Name, oldPV); err != nil { 151 t.Fatalf("Failed to GetPV() after initial update: %v", err) 152 } 153 154 // Restore PV 155 cache.Restore(oldPV.Name) 156 if err := verifyPV(cache, oldPV.Name, oldPV); err != nil { 157 t.Fatalf("Failed to GetPV() after initial restore: %v", err) 158 } 159 160 // Assume newPV 161 if err := cache.Assume(newPV); err != nil { 162 t.Fatalf("Assume() returned error %v", err) 163 } 164 if err := verifyPV(cache, oldPV.Name, newPV); err != nil { 165 t.Fatalf("Failed to GetPV() after Assume: %v", err) 166 } 167 168 // Restore PV 169 cache.Restore(oldPV.Name) 170 if err := verifyPV(cache, oldPV.Name, oldPV); err != nil { 171 t.Fatalf("Failed to GetPV() after restore: %v", err) 172 } 173 } 174 175 func TestBasicPVCache(t *testing.T) { 176 logger, _ := ktesting.NewTestContext(t) 177 cache := NewPVAssumeCache(logger, nil) 178 internalCache, ok := cache.(*pvAssumeCache).AssumeCache.(*assumeCache) 179 if !ok { 180 t.Fatalf("Failed to get internal cache") 181 } 182 183 // Get object that doesn't exist 184 pv, err := cache.GetPV("nothere") 185 if err == nil { 186 t.Errorf("GetPV() returned unexpected success") 187 } 188 if pv != nil { 189 t.Errorf("GetPV() returned unexpected PV %q", pv.Name) 190 } 191 192 // Add a bunch of PVs 193 pvs := map[string]*v1.PersistentVolume{} 194 for i := 0; i < 10; i++ { 195 pv := makePV(fmt.Sprintf("test-pv%v", i), "").withVersion("1").PersistentVolume 196 pvs[pv.Name] = pv 197 internalCache.add(pv) 198 } 199 200 // List them 201 verifyListPVs(t, cache, pvs, "") 202 203 // Update a PV 204 updatedPV := makePV("test-pv3", "").withVersion("2").PersistentVolume 205 pvs[updatedPV.Name] = updatedPV 206 internalCache.update(nil, updatedPV) 207 208 // List them 209 verifyListPVs(t, cache, pvs, "") 210 211 // Delete a PV 212 deletedPV := pvs["test-pv7"] 213 delete(pvs, deletedPV.Name) 214 internalCache.delete(deletedPV) 215 216 // List them 217 verifyListPVs(t, cache, pvs, "") 218 } 219 220 func TestPVCacheWithStorageClasses(t *testing.T) { 221 logger, _ := ktesting.NewTestContext(t) 222 cache := NewPVAssumeCache(logger, nil) 223 internalCache, ok := cache.(*pvAssumeCache).AssumeCache.(*assumeCache) 224 if !ok { 225 t.Fatalf("Failed to get internal cache") 226 } 227 228 // Add a bunch of PVs 229 pvs1 := map[string]*v1.PersistentVolume{} 230 for i := 0; i < 10; i++ { 231 pv := makePV(fmt.Sprintf("test-pv%v", i), "class1").withVersion("1").PersistentVolume 232 pvs1[pv.Name] = pv 233 internalCache.add(pv) 234 } 235 236 // Add a bunch of PVs 237 pvs2 := map[string]*v1.PersistentVolume{} 238 for i := 0; i < 10; i++ { 239 pv := makePV(fmt.Sprintf("test2-pv%v", i), "class2").withVersion("1").PersistentVolume 240 pvs2[pv.Name] = pv 241 internalCache.add(pv) 242 } 243 244 // List them 245 verifyListPVs(t, cache, pvs1, "class1") 246 verifyListPVs(t, cache, pvs2, "class2") 247 248 // Update a PV 249 updatedPV := makePV("test-pv3", "class1").withVersion("2").PersistentVolume 250 pvs1[updatedPV.Name] = updatedPV 251 internalCache.update(nil, updatedPV) 252 253 // List them 254 verifyListPVs(t, cache, pvs1, "class1") 255 verifyListPVs(t, cache, pvs2, "class2") 256 257 // Delete a PV 258 deletedPV := pvs1["test-pv7"] 259 delete(pvs1, deletedPV.Name) 260 internalCache.delete(deletedPV) 261 262 // List them 263 verifyListPVs(t, cache, pvs1, "class1") 264 verifyListPVs(t, cache, pvs2, "class2") 265 } 266 267 func TestAssumeUpdatePVCache(t *testing.T) { 268 logger, _ := ktesting.NewTestContext(t) 269 cache := NewPVAssumeCache(logger, nil) 270 internalCache, ok := cache.(*pvAssumeCache).AssumeCache.(*assumeCache) 271 if !ok { 272 t.Fatalf("Failed to get internal cache") 273 } 274 275 pvName := "test-pv0" 276 277 // Add a PV 278 pv := makePV(pvName, "").withVersion("1").PersistentVolume 279 internalCache.add(pv) 280 if err := verifyPV(cache, pvName, pv); err != nil { 281 t.Fatalf("failed to get PV: %v", err) 282 } 283 284 // Assume PV 285 newPV := pv.DeepCopy() 286 newPV.Spec.ClaimRef = &v1.ObjectReference{Name: "test-claim"} 287 if err := cache.Assume(newPV); err != nil { 288 t.Fatalf("failed to assume PV: %v", err) 289 } 290 if err := verifyPV(cache, pvName, newPV); err != nil { 291 t.Fatalf("failed to get PV after assume: %v", err) 292 } 293 294 // Add old PV 295 internalCache.add(pv) 296 if err := verifyPV(cache, pvName, newPV); err != nil { 297 t.Fatalf("failed to get PV after old PV added: %v", err) 298 } 299 } 300 301 func makeClaim(name, version, namespace string) *v1.PersistentVolumeClaim { 302 return &v1.PersistentVolumeClaim{ 303 ObjectMeta: metav1.ObjectMeta{ 304 Name: name, 305 Namespace: namespace, 306 ResourceVersion: version, 307 Annotations: map[string]string{}, 308 }, 309 } 310 } 311 312 func verifyPVC(cache PVCAssumeCache, pvcKey string, expectedPVC *v1.PersistentVolumeClaim) error { 313 pvc, err := cache.GetPVC(pvcKey) 314 if err != nil { 315 return err 316 } 317 if pvc != expectedPVC { 318 return fmt.Errorf("GetPVC() returned %p, expected %p", pvc, expectedPVC) 319 } 320 return nil 321 } 322 323 func TestAssumePVC(t *testing.T) { 324 logger, _ := ktesting.NewTestContext(t) 325 scenarios := map[string]struct { 326 oldPVC *v1.PersistentVolumeClaim 327 newPVC *v1.PersistentVolumeClaim 328 shouldSucceed bool 329 }{ 330 "success-same-version": { 331 oldPVC: makeClaim("pvc1", "5", "ns1"), 332 newPVC: makeClaim("pvc1", "5", "ns1"), 333 shouldSucceed: true, 334 }, 335 "success-new-higher-version": { 336 oldPVC: makeClaim("pvc1", "5", "ns1"), 337 newPVC: makeClaim("pvc1", "6", "ns1"), 338 shouldSucceed: true, 339 }, 340 "fail-old-not-found": { 341 oldPVC: makeClaim("pvc2", "5", "ns1"), 342 newPVC: makeClaim("pvc1", "5", "ns1"), 343 shouldSucceed: false, 344 }, 345 "fail-new-lower-version": { 346 oldPVC: makeClaim("pvc1", "5", "ns1"), 347 newPVC: makeClaim("pvc1", "4", "ns1"), 348 shouldSucceed: false, 349 }, 350 "fail-new-bad-version": { 351 oldPVC: makeClaim("pvc1", "5", "ns1"), 352 newPVC: makeClaim("pvc1", "a", "ns1"), 353 shouldSucceed: false, 354 }, 355 "fail-old-bad-version": { 356 oldPVC: makeClaim("pvc1", "a", "ns1"), 357 newPVC: makeClaim("pvc1", "5", "ns1"), 358 shouldSucceed: false, 359 }, 360 } 361 362 for name, scenario := range scenarios { 363 cache := NewPVCAssumeCache(logger, nil) 364 internalCache, ok := cache.(*pvcAssumeCache).AssumeCache.(*assumeCache) 365 if !ok { 366 t.Fatalf("Failed to get internal cache") 367 } 368 369 // Add oldPVC to cache 370 internalCache.add(scenario.oldPVC) 371 if err := verifyPVC(cache, getPVCName(scenario.oldPVC), scenario.oldPVC); err != nil { 372 t.Errorf("Failed to GetPVC() after initial update: %v", err) 373 continue 374 } 375 376 // Assume newPVC 377 err := cache.Assume(scenario.newPVC) 378 if scenario.shouldSucceed && err != nil { 379 t.Errorf("Test %q failed: Assume() returned error %v", name, err) 380 } 381 if !scenario.shouldSucceed && err == nil { 382 t.Errorf("Test %q failed: Assume() returned success but expected error", name) 383 } 384 385 // Check that GetPVC returns correct PVC 386 expectedPV := scenario.newPVC 387 if !scenario.shouldSucceed { 388 expectedPV = scenario.oldPVC 389 } 390 if err := verifyPVC(cache, getPVCName(scenario.oldPVC), expectedPV); err != nil { 391 t.Errorf("Failed to GetPVC() after initial update: %v", err) 392 } 393 } 394 } 395 396 func TestRestorePVC(t *testing.T) { 397 logger, _ := ktesting.NewTestContext(t) 398 cache := NewPVCAssumeCache(logger, nil) 399 internalCache, ok := cache.(*pvcAssumeCache).AssumeCache.(*assumeCache) 400 if !ok { 401 t.Fatalf("Failed to get internal cache") 402 } 403 404 oldPVC := makeClaim("pvc1", "5", "ns1") 405 newPVC := makeClaim("pvc1", "5", "ns1") 406 407 // Restore PVC that doesn't exist 408 cache.Restore("nothing") 409 410 // Add oldPVC to cache 411 internalCache.add(oldPVC) 412 if err := verifyPVC(cache, getPVCName(oldPVC), oldPVC); err != nil { 413 t.Fatalf("Failed to GetPVC() after initial update: %v", err) 414 } 415 416 // Restore PVC 417 cache.Restore(getPVCName(oldPVC)) 418 if err := verifyPVC(cache, getPVCName(oldPVC), oldPVC); err != nil { 419 t.Fatalf("Failed to GetPVC() after initial restore: %v", err) 420 } 421 422 // Assume newPVC 423 if err := cache.Assume(newPVC); err != nil { 424 t.Fatalf("Assume() returned error %v", err) 425 } 426 if err := verifyPVC(cache, getPVCName(oldPVC), newPVC); err != nil { 427 t.Fatalf("Failed to GetPVC() after Assume: %v", err) 428 } 429 430 // Restore PVC 431 cache.Restore(getPVCName(oldPVC)) 432 if err := verifyPVC(cache, getPVCName(oldPVC), oldPVC); err != nil { 433 t.Fatalf("Failed to GetPVC() after restore: %v", err) 434 } 435 } 436 437 func TestAssumeUpdatePVCCache(t *testing.T) { 438 logger, _ := ktesting.NewTestContext(t) 439 cache := NewPVCAssumeCache(logger, nil) 440 internalCache, ok := cache.(*pvcAssumeCache).AssumeCache.(*assumeCache) 441 if !ok { 442 t.Fatalf("Failed to get internal cache") 443 } 444 445 pvcName := "test-pvc0" 446 pvcNamespace := "test-ns" 447 448 // Add a PVC 449 pvc := makeClaim(pvcName, "1", pvcNamespace) 450 internalCache.add(pvc) 451 if err := verifyPVC(cache, getPVCName(pvc), pvc); err != nil { 452 t.Fatalf("failed to get PVC: %v", err) 453 } 454 455 // Assume PVC 456 newPVC := pvc.DeepCopy() 457 newPVC.Annotations[volume.AnnSelectedNode] = "test-node" 458 if err := cache.Assume(newPVC); err != nil { 459 t.Fatalf("failed to assume PVC: %v", err) 460 } 461 if err := verifyPVC(cache, getPVCName(pvc), newPVC); err != nil { 462 t.Fatalf("failed to get PVC after assume: %v", err) 463 } 464 465 // Add old PVC 466 internalCache.add(pvc) 467 if err := verifyPVC(cache, getPVCName(pvc), newPVC); err != nil { 468 t.Fatalf("failed to get PVC after old PVC added: %v", err) 469 } 470 }