k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/scheduler/framework/plugins/volumezone/volume_zone_test.go (about) 1 /* 2 Copyright 2019 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 volumezone 18 19 import ( 20 "context" 21 "fmt" 22 "testing" 23 24 "github.com/google/go-cmp/cmp" 25 v1 "k8s.io/api/core/v1" 26 storagev1 "k8s.io/api/storage/v1" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 "k8s.io/apimachinery/pkg/runtime" 29 "k8s.io/klog/v2/ktesting" 30 "k8s.io/kubernetes/pkg/scheduler/apis/config" 31 "k8s.io/kubernetes/pkg/scheduler/framework" 32 plugintesting "k8s.io/kubernetes/pkg/scheduler/framework/plugins/testing" 33 "k8s.io/kubernetes/pkg/scheduler/internal/cache" 34 st "k8s.io/kubernetes/pkg/scheduler/testing" 35 tf "k8s.io/kubernetes/pkg/scheduler/testing/framework" 36 ) 37 38 func createPodWithVolume(pod, pvc string) *v1.Pod { 39 return st.MakePod().Name(pod).Namespace(metav1.NamespaceDefault).PVC(pvc).Obj() 40 } 41 42 func TestSingleZone(t *testing.T) { 43 pvLister := tf.PersistentVolumeLister{ 44 { 45 ObjectMeta: metav1.ObjectMeta{Name: "Vol_1", Labels: map[string]string{v1.LabelFailureDomainBetaZone: "us-west1-a"}}, 46 }, 47 { 48 ObjectMeta: metav1.ObjectMeta{Name: "Vol_2", Labels: map[string]string{v1.LabelFailureDomainBetaRegion: "us-west1", "uselessLabel": "none"}}, 49 }, 50 { 51 ObjectMeta: metav1.ObjectMeta{Name: "Vol_3", Labels: map[string]string{v1.LabelFailureDomainBetaRegion: "us-west1"}}, 52 }, 53 { 54 ObjectMeta: metav1.ObjectMeta{Name: "Vol_Stable_1", Labels: map[string]string{v1.LabelTopologyZone: "us-west1-a"}}, 55 }, 56 { 57 ObjectMeta: metav1.ObjectMeta{Name: "Vol_Stable_2", Labels: map[string]string{v1.LabelTopologyRegion: "us-west1", "uselessLabel": "none"}}, 58 }, 59 { 60 ObjectMeta: metav1.ObjectMeta{Name: "Vol_Stable_3", Labels: map[string]string{v1.LabelTopologyZone: "us-west1-a", v1.LabelTopologyRegion: "us-west1-a"}}, 61 }, 62 } 63 64 pvcLister := tf.PersistentVolumeClaimLister{ 65 { 66 ObjectMeta: metav1.ObjectMeta{Name: "PVC_1", Namespace: "default"}, 67 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_1"}, 68 }, 69 { 70 ObjectMeta: metav1.ObjectMeta{Name: "PVC_2", Namespace: "default"}, 71 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_2"}, 72 }, 73 { 74 ObjectMeta: metav1.ObjectMeta{Name: "PVC_3", Namespace: "default"}, 75 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_3"}, 76 }, 77 { 78 ObjectMeta: metav1.ObjectMeta{Name: "PVC_4", Namespace: "default"}, 79 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_not_exist"}, 80 }, 81 { 82 ObjectMeta: metav1.ObjectMeta{Name: "PVC_Stable_1", Namespace: "default"}, 83 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_Stable_1"}, 84 }, 85 { 86 ObjectMeta: metav1.ObjectMeta{Name: "PVC_Stable_2", Namespace: "default"}, 87 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_Stable_2"}, 88 }, 89 { 90 ObjectMeta: metav1.ObjectMeta{Name: "PVC_Stable_3", Namespace: "default"}, 91 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_Stable_3"}, 92 }, 93 } 94 95 tests := []struct { 96 name string 97 Pod *v1.Pod 98 Node *v1.Node 99 wantPreFilterStatus *framework.Status 100 wantFilterStatus *framework.Status 101 }{ 102 { 103 name: "pod without volume", 104 Pod: st.MakePod().Name("pod_1").Namespace(metav1.NamespaceDefault).Obj(), 105 Node: &v1.Node{ 106 ObjectMeta: metav1.ObjectMeta{ 107 Name: "host1", 108 Labels: map[string]string{v1.LabelFailureDomainBetaZone: "us-west1-a"}, 109 }, 110 }, 111 wantPreFilterStatus: framework.NewStatus(framework.Skip), 112 }, 113 { 114 name: "node without labels", 115 Pod: createPodWithVolume("pod_1", "PVC_1"), 116 Node: &v1.Node{ 117 ObjectMeta: metav1.ObjectMeta{ 118 Name: "host1", 119 }, 120 }, 121 }, 122 { 123 name: "beta zone label matched", 124 Pod: createPodWithVolume("pod_1", "PVC_1"), 125 Node: &v1.Node{ 126 ObjectMeta: metav1.ObjectMeta{ 127 Name: "host1", 128 Labels: map[string]string{v1.LabelFailureDomainBetaZone: "us-west1-a", "uselessLabel": "none"}, 129 }, 130 }, 131 }, 132 { 133 name: "beta region label matched", 134 Pod: createPodWithVolume("pod_1", "PVC_2"), 135 Node: &v1.Node{ 136 ObjectMeta: metav1.ObjectMeta{ 137 Name: "host1", 138 Labels: map[string]string{v1.LabelFailureDomainBetaRegion: "us-west1", "uselessLabel": "none"}, 139 }, 140 }, 141 }, 142 { 143 name: "beta region label doesn't match", 144 Pod: createPodWithVolume("pod_1", "PVC_2"), 145 Node: &v1.Node{ 146 ObjectMeta: metav1.ObjectMeta{ 147 Name: "host1", 148 Labels: map[string]string{v1.LabelFailureDomainBetaRegion: "no_us-west1", "uselessLabel": "none"}, 149 }, 150 }, 151 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonConflict), 152 }, 153 { 154 name: "beta zone label doesn't match", 155 Pod: createPodWithVolume("pod_1", "PVC_1"), 156 Node: &v1.Node{ 157 ObjectMeta: metav1.ObjectMeta{ 158 Name: "host1", 159 Labels: map[string]string{v1.LabelFailureDomainBetaZone: "no_us-west1-a", "uselessLabel": "none"}, 160 }, 161 }, 162 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonConflict), 163 }, 164 { 165 name: "zone label matched", 166 Pod: createPodWithVolume("pod_1", "PVC_Stable_1"), 167 Node: &v1.Node{ 168 ObjectMeta: metav1.ObjectMeta{ 169 Name: "host1", 170 Labels: map[string]string{v1.LabelTopologyZone: "us-west1-a", "uselessLabel": "none"}, 171 }, 172 }, 173 }, 174 { 175 name: "region label matched", 176 Pod: createPodWithVolume("pod_1", "PVC_Stable_2"), 177 Node: &v1.Node{ 178 ObjectMeta: metav1.ObjectMeta{ 179 Name: "host1", 180 Labels: map[string]string{v1.LabelTopologyRegion: "us-west1", "uselessLabel": "none"}, 181 }, 182 }, 183 }, 184 { 185 name: "region label doesn't match", 186 Pod: createPodWithVolume("pod_1", "PVC_Stable_2"), 187 Node: &v1.Node{ 188 ObjectMeta: metav1.ObjectMeta{ 189 Name: "host1", 190 Labels: map[string]string{v1.LabelTopologyRegion: "no_us-west1", "uselessLabel": "none"}, 191 }, 192 }, 193 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonConflict), 194 }, 195 { 196 name: "zone label doesn't match", 197 Pod: createPodWithVolume("pod_1", "PVC_Stable_1"), 198 Node: &v1.Node{ 199 ObjectMeta: metav1.ObjectMeta{ 200 Name: "host1", 201 Labels: map[string]string{v1.LabelTopologyZone: "no_us-west1-a", "uselessLabel": "none"}, 202 }, 203 }, 204 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonConflict), 205 }, 206 { 207 name: "pv with zone and region, node with only zone", 208 Pod: createPodWithVolume("pod_1", "PVC_Stable_3"), 209 Node: &v1.Node{ 210 ObjectMeta: metav1.ObjectMeta{ 211 Name: "host1", 212 Labels: map[string]string{ 213 v1.LabelTopologyZone: "us-west1-a", 214 }, 215 }, 216 }, 217 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonConflict), 218 }, 219 { 220 name: "pv with zone,node with beta zone", 221 Pod: createPodWithVolume("pod_1", "PVC_Stable_1"), 222 Node: &v1.Node{ 223 ObjectMeta: metav1.ObjectMeta{ 224 Name: "host1", 225 Labels: map[string]string{ 226 v1.LabelFailureDomainBetaZone: "us-west1-a", 227 }, 228 }, 229 }, 230 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonConflict), 231 }, 232 { 233 name: "pv with beta label,node with ga label, matched", 234 Pod: createPodWithVolume("pod_1", "PVC_1"), 235 Node: &v1.Node{ 236 ObjectMeta: metav1.ObjectMeta{ 237 Name: "host1", 238 Labels: map[string]string{ 239 v1.LabelTopologyZone: "us-west1-a", 240 }, 241 }, 242 }, 243 }, 244 { 245 name: "pv with beta label,node with ga label, don't match", 246 Pod: createPodWithVolume("pod_1", "PVC_1"), 247 Node: &v1.Node{ 248 ObjectMeta: metav1.ObjectMeta{ 249 Name: "host1", 250 Labels: map[string]string{ 251 v1.LabelTopologyZone: "us-west1-b", 252 }, 253 }, 254 }, 255 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonConflict), 256 }, 257 } 258 259 for _, test := range tests { 260 t.Run(test.name, func(t *testing.T) { 261 _, ctx := ktesting.NewTestContext(t) 262 ctx, cancel := context.WithCancel(ctx) 263 defer cancel() 264 265 state := framework.NewCycleState() 266 node := &framework.NodeInfo{} 267 node.SetNode(test.Node) 268 p := &VolumeZone{ 269 pvLister, 270 pvcLister, 271 nil, 272 } 273 _, preFilterStatus := p.PreFilter(ctx, state, test.Pod) 274 if diff := cmp.Diff(preFilterStatus, test.wantPreFilterStatus); diff != "" { 275 t.Errorf("PreFilter: status does not match (-want,+got):\n%s", diff) 276 } 277 filterStatus := p.Filter(ctx, state, test.Pod, node) 278 if diff := cmp.Diff(filterStatus, test.wantFilterStatus); diff != "" { 279 t.Errorf("Filter: status does not match (-want,+got):\n%s", diff) 280 } 281 }) 282 } 283 } 284 285 func TestMultiZone(t *testing.T) { 286 pvLister := tf.PersistentVolumeLister{ 287 { 288 ObjectMeta: metav1.ObjectMeta{Name: "Vol_1", Labels: map[string]string{v1.LabelFailureDomainBetaZone: "us-west1-a"}}, 289 }, 290 { 291 ObjectMeta: metav1.ObjectMeta{Name: "Vol_2", Labels: map[string]string{v1.LabelFailureDomainBetaZone: "us-west1-b", "uselessLabel": "none"}}, 292 }, 293 { 294 ObjectMeta: metav1.ObjectMeta{Name: "Vol_3", Labels: map[string]string{v1.LabelFailureDomainBetaZone: "us-west1-c__us-west1-a"}}, 295 }, 296 { 297 ObjectMeta: metav1.ObjectMeta{Name: "Vol_Stable_1", Labels: map[string]string{v1.LabelTopologyZone: "us-west1-a"}}, 298 }, 299 { 300 ObjectMeta: metav1.ObjectMeta{Name: "Vol_Stable_2", Labels: map[string]string{v1.LabelTopologyZone: "us-west1-c__us-west1-a"}}, 301 }, 302 } 303 304 pvcLister := tf.PersistentVolumeClaimLister{ 305 { 306 ObjectMeta: metav1.ObjectMeta{Name: "PVC_1", Namespace: "default"}, 307 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_1"}, 308 }, 309 { 310 ObjectMeta: metav1.ObjectMeta{Name: "PVC_2", Namespace: "default"}, 311 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_2"}, 312 }, 313 { 314 ObjectMeta: metav1.ObjectMeta{Name: "PVC_3", Namespace: "default"}, 315 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_3"}, 316 }, 317 { 318 ObjectMeta: metav1.ObjectMeta{Name: "PVC_4", Namespace: "default"}, 319 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_not_exist"}, 320 }, 321 { 322 ObjectMeta: metav1.ObjectMeta{Name: "PVC_Stable_1", Namespace: "default"}, 323 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_Stable_1"}, 324 }, 325 { 326 ObjectMeta: metav1.ObjectMeta{Name: "PVC_Stable_2", Namespace: "default"}, 327 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_Stable_2"}, 328 }, 329 } 330 331 tests := []struct { 332 name string 333 Pod *v1.Pod 334 Node *v1.Node 335 wantPreFilterStatus *framework.Status 336 wantFilterStatus *framework.Status 337 }{ 338 { 339 name: "node without labels", 340 Pod: createPodWithVolume("pod_1", "PVC_3"), 341 Node: &v1.Node{ 342 ObjectMeta: metav1.ObjectMeta{ 343 Name: "host1", 344 }, 345 }, 346 }, 347 { 348 name: "beta zone label matched", 349 Pod: createPodWithVolume("pod_1", "PVC_3"), 350 Node: &v1.Node{ 351 ObjectMeta: metav1.ObjectMeta{ 352 Name: "host1", 353 Labels: map[string]string{v1.LabelFailureDomainBetaZone: "us-west1-a", "uselessLabel": "none"}, 354 }, 355 }, 356 }, 357 { 358 name: "beta zone label doesn't match", 359 Pod: createPodWithVolume("pod_1", "PVC_1"), 360 Node: &v1.Node{ 361 ObjectMeta: metav1.ObjectMeta{ 362 Name: "host1", 363 Labels: map[string]string{v1.LabelFailureDomainBetaZone: "us-west1-b", "uselessLabel": "none"}, 364 }, 365 }, 366 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonConflict), 367 }, 368 { 369 name: "zone label matched", 370 Pod: createPodWithVolume("pod_1", "PVC_Stable_2"), 371 Node: &v1.Node{ 372 ObjectMeta: metav1.ObjectMeta{ 373 Name: "host1", 374 Labels: map[string]string{v1.LabelTopologyZone: "us-west1-a", "uselessLabel": "none"}, 375 }, 376 }, 377 }, 378 { 379 name: "zone label doesn't match", 380 Pod: createPodWithVolume("pod_1", "PVC_Stable_1"), 381 Node: &v1.Node{ 382 ObjectMeta: metav1.ObjectMeta{ 383 Name: "host1", 384 Labels: map[string]string{v1.LabelTopologyZone: "us-west1-b", "uselessLabel": "none"}, 385 }, 386 }, 387 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonConflict), 388 }, 389 } 390 391 for _, test := range tests { 392 t.Run(test.name, func(t *testing.T) { 393 _, ctx := ktesting.NewTestContext(t) 394 ctx, cancel := context.WithCancel(ctx) 395 defer cancel() 396 397 state := framework.NewCycleState() 398 node := &framework.NodeInfo{} 399 node.SetNode(test.Node) 400 p := &VolumeZone{ 401 pvLister, 402 pvcLister, 403 nil, 404 } 405 _, preFilterStatus := p.PreFilter(ctx, state, test.Pod) 406 if diff := cmp.Diff(preFilterStatus, test.wantPreFilterStatus); diff != "" { 407 t.Errorf("PreFilter: status does not match (-want,+got):\n%s", diff) 408 } 409 filterStatus := p.Filter(ctx, state, test.Pod, node) 410 if diff := cmp.Diff(filterStatus, test.wantFilterStatus); diff != "" { 411 t.Errorf("Filter: status does not match (-want,+got):\n%s", diff) 412 } 413 }) 414 } 415 } 416 417 func TestWithBinding(t *testing.T) { 418 var ( 419 modeWait = storagev1.VolumeBindingWaitForFirstConsumer 420 421 class0 = "Class_0" 422 classWait = "Class_Wait" 423 classImmediate = "Class_Immediate" 424 ) 425 426 scLister := tf.StorageClassLister{ 427 { 428 ObjectMeta: metav1.ObjectMeta{Name: classImmediate}, 429 }, 430 { 431 ObjectMeta: metav1.ObjectMeta{Name: classWait}, 432 VolumeBindingMode: &modeWait, 433 }, 434 } 435 436 pvLister := tf.PersistentVolumeLister{ 437 { 438 ObjectMeta: metav1.ObjectMeta{Name: "Vol_1", Labels: map[string]string{v1.LabelFailureDomainBetaZone: "us-west1-a"}}, 439 }, 440 } 441 442 pvcLister := tf.PersistentVolumeClaimLister{ 443 { 444 ObjectMeta: metav1.ObjectMeta{Name: "PVC_1", Namespace: "default"}, 445 Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_1"}, 446 }, 447 { 448 ObjectMeta: metav1.ObjectMeta{Name: "PVC_NoSC", Namespace: "default"}, 449 Spec: v1.PersistentVolumeClaimSpec{StorageClassName: &class0}, 450 }, 451 { 452 ObjectMeta: metav1.ObjectMeta{Name: "PVC_EmptySC", Namespace: "default"}, 453 }, 454 { 455 ObjectMeta: metav1.ObjectMeta{Name: "PVC_WaitSC", Namespace: "default"}, 456 Spec: v1.PersistentVolumeClaimSpec{StorageClassName: &classWait}, 457 }, 458 { 459 ObjectMeta: metav1.ObjectMeta{Name: "PVC_ImmediateSC", Namespace: "default"}, 460 Spec: v1.PersistentVolumeClaimSpec{StorageClassName: &classImmediate}, 461 }, 462 } 463 464 testNode := &v1.Node{ 465 ObjectMeta: metav1.ObjectMeta{ 466 Name: "host1", 467 Labels: map[string]string{v1.LabelFailureDomainBetaZone: "us-west1-a", "uselessLabel": "none"}, 468 }, 469 } 470 471 tests := []struct { 472 name string 473 Pod *v1.Pod 474 Node *v1.Node 475 wantPreFilterStatus *framework.Status 476 wantFilterStatus *framework.Status 477 }{ 478 { 479 name: "label zone failure domain matched", 480 Pod: createPodWithVolume("pod_1", "PVC_1"), 481 Node: testNode, 482 }, 483 { 484 name: "unbound volume empty storage class", 485 Pod: createPodWithVolume("pod_1", "PVC_EmptySC"), 486 Node: testNode, 487 wantPreFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, 488 "PersistentVolumeClaim had no pv name and storageClass name"), 489 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, 490 "PersistentVolumeClaim had no pv name and storageClass name"), 491 }, 492 { 493 name: "unbound volume no storage class", 494 Pod: createPodWithVolume("pod_1", "PVC_NoSC"), 495 Node: testNode, 496 wantPreFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, 497 `storageclasses.storage.k8s.io "Class_0" not found`), 498 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, 499 `storageclasses.storage.k8s.io "Class_0" not found`), 500 }, 501 { 502 name: "unbound volume immediate binding mode", 503 Pod: createPodWithVolume("pod_1", "PVC_ImmediateSC"), 504 Node: testNode, 505 wantPreFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, "VolumeBindingMode not set for StorageClass \"Class_Immediate\""), 506 wantFilterStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, "VolumeBindingMode not set for StorageClass \"Class_Immediate\""), 507 }, 508 { 509 name: "unbound volume wait binding mode", 510 Pod: createPodWithVolume("pod_1", "PVC_WaitSC"), 511 Node: testNode, 512 wantPreFilterStatus: framework.NewStatus(framework.Skip), 513 }, 514 } 515 516 for _, test := range tests { 517 t.Run(test.name, func(t *testing.T) { 518 _, ctx := ktesting.NewTestContext(t) 519 ctx, cancel := context.WithCancel(ctx) 520 defer cancel() 521 522 state := framework.NewCycleState() 523 node := &framework.NodeInfo{} 524 node.SetNode(test.Node) 525 p := &VolumeZone{ 526 pvLister, 527 pvcLister, 528 scLister, 529 } 530 _, preFilterStatus := p.PreFilter(ctx, state, test.Pod) 531 if diff := cmp.Diff(preFilterStatus, test.wantPreFilterStatus); diff != "" { 532 t.Errorf("PreFilter: status does not match (-want,+got):\n%s", diff) 533 } 534 filterStatus := p.Filter(ctx, state, test.Pod, node) 535 if diff := cmp.Diff(filterStatus, test.wantFilterStatus); diff != "" { 536 t.Errorf("Filter: status does not match (-want,+got):\n%s", diff) 537 } 538 }) 539 } 540 } 541 542 func BenchmarkVolumeZone(b *testing.B) { 543 tests := []struct { 544 Name string 545 Pod *v1.Pod 546 NumPV int 547 NumPVC int 548 NumNodes int 549 PreFilter bool 550 }{ 551 { 552 Name: "with prefilter", 553 Pod: createPodWithVolume("pod_0", "PVC_Stable_0"), 554 NumPV: 1000, 555 NumPVC: 1000, 556 NumNodes: 1000, 557 PreFilter: true, 558 }, 559 { 560 Name: "without prefilter", 561 Pod: createPodWithVolume("pod_0", "PVC_Stable_0"), 562 NumPV: 1000, 563 NumPVC: 1000, 564 NumNodes: 1000, 565 PreFilter: false, 566 }, 567 } 568 569 for _, tt := range tests { 570 b.Run(tt.Name, func(b *testing.B) { 571 ctx, cancel := context.WithCancel(context.Background()) 572 defer cancel() 573 nodes := makeNodesWithTopologyZone(tt.NumNodes) 574 pl := newPluginWithListers(ctx, b, []*v1.Pod{tt.Pod}, nodes, makePVCsWithPV(tt.NumPVC), makePVsWithZoneLabel(tt.NumPV)) 575 nodeInfos := make([]*framework.NodeInfo, len(nodes), len(nodes)) 576 for i := 0; i < len(nodes); i++ { 577 nodeInfo := &framework.NodeInfo{} 578 nodeInfo.SetNode(nodes[i]) 579 nodeInfos[i] = nodeInfo 580 } 581 p := pl.(*VolumeZone) 582 state := framework.NewCycleState() 583 584 b.ResetTimer() 585 586 for i := 0; i < b.N; i++ { 587 if tt.PreFilter { 588 _, _ = p.PreFilter(ctx, state, tt.Pod) 589 } 590 for _, node := range nodeInfos { 591 _ = p.Filter(ctx, state, tt.Pod, node) 592 } 593 } 594 }) 595 } 596 } 597 598 func newPluginWithListers(ctx context.Context, tb testing.TB, pods []*v1.Pod, nodes []*v1.Node, pvcs []*v1.PersistentVolumeClaim, pvs []*v1.PersistentVolume) framework.Plugin { 599 snapshot := cache.NewSnapshot(pods, nodes) 600 601 objects := make([]runtime.Object, 0, len(pvcs)) 602 for _, pvc := range pvcs { 603 objects = append(objects, pvc) 604 } 605 for _, pv := range pvs { 606 objects = append(objects, pv) 607 } 608 return plugintesting.SetupPluginWithInformers(ctx, tb, New, &config.InterPodAffinityArgs{}, snapshot, objects) 609 } 610 611 func makePVsWithZoneLabel(num int) []*v1.PersistentVolume { 612 pvList := make([]*v1.PersistentVolume, num, num) 613 for i := 0; i < len(pvList); i++ { 614 pvName := fmt.Sprintf("Vol_Stable_%d", i) 615 zone := fmt.Sprintf("us-west-%d", i) 616 pvList[i] = &v1.PersistentVolume{ 617 ObjectMeta: metav1.ObjectMeta{Name: pvName, Labels: map[string]string{v1.LabelTopologyZone: zone}}, 618 } 619 } 620 return pvList 621 } 622 623 func makePVCsWithPV(num int) []*v1.PersistentVolumeClaim { 624 pvcList := make([]*v1.PersistentVolumeClaim, num, num) 625 for i := 0; i < len(pvcList); i++ { 626 pvcName := fmt.Sprintf("PVC_Stable_%d", i) 627 pvName := fmt.Sprintf("Vol_Stable_%d", i) 628 pvcList[i] = &v1.PersistentVolumeClaim{ 629 ObjectMeta: metav1.ObjectMeta{Name: pvcName, Namespace: "default"}, 630 Spec: v1.PersistentVolumeClaimSpec{VolumeName: pvName}, 631 } 632 } 633 return pvcList 634 } 635 636 func makeNodesWithTopologyZone(num int) []*v1.Node { 637 nodeList := make([]*v1.Node, num, num) 638 for i := 0; i < len(nodeList); i++ { 639 nodeName := fmt.Sprintf("host_%d", i) 640 zone := fmt.Sprintf("us-west-0") 641 nodeList[i] = &v1.Node{ 642 ObjectMeta: metav1.ObjectMeta{ 643 Name: nodeName, 644 Labels: map[string]string{v1.LabelTopologyZone: zone, "uselessLabel": "none"}, 645 }, 646 } 647 } 648 return nodeList 649 }