github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/cnr_test.go (about) 1 /* 2 Copyright 2022 The Katalyst 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 util 18 19 import ( 20 "fmt" 21 "testing" 22 23 "github.com/stretchr/testify/assert" 24 v1 "k8s.io/api/core/v1" 25 "k8s.io/apimachinery/pkg/api/resource" 26 27 nodeapis "github.com/kubewharf/katalyst-api/pkg/apis/node/v1alpha1" 28 ) 29 30 func TestAddOrUpdateCNRTaint(t *testing.T) { 31 t.Parallel() 32 33 type args struct { 34 cnr *nodeapis.CustomNodeResource 35 taint *nodeapis.Taint 36 } 37 tests := []struct { 38 name string 39 args args 40 want *nodeapis.CustomNodeResource 41 want1 bool 42 wantErr assert.ErrorAssertionFunc 43 }{ 44 { 45 name: "add taint", 46 args: args{ 47 cnr: &nodeapis.CustomNodeResource{}, 48 taint: &nodeapis.Taint{ 49 Key: "test-key", 50 Value: "test-value", 51 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 52 }, 53 }, 54 want: &nodeapis.CustomNodeResource{ 55 Spec: nodeapis.CustomNodeResourceSpec{ 56 Taints: []*nodeapis.Taint{ 57 { 58 Key: "test-key", 59 Value: "test-value", 60 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 61 }, 62 }, 63 }, 64 }, 65 want1: true, 66 wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { 67 return true 68 }, 69 }, 70 { 71 name: "update taint", 72 args: args{ 73 cnr: &nodeapis.CustomNodeResource{ 74 Spec: nodeapis.CustomNodeResourceSpec{ 75 Taints: []*nodeapis.Taint{ 76 { 77 Key: "test-key", 78 Value: "test-value", 79 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 80 }, 81 }, 82 }, 83 }, 84 taint: &nodeapis.Taint{ 85 Key: "test-key", 86 Value: "test-value-1", 87 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 88 }, 89 }, 90 want: &nodeapis.CustomNodeResource{ 91 Spec: nodeapis.CustomNodeResourceSpec{ 92 Taints: []*nodeapis.Taint{ 93 { 94 Key: "test-key", 95 Value: "test-value-1", 96 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 97 }, 98 }, 99 }, 100 }, 101 want1: true, 102 wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { 103 return true 104 }, 105 }, 106 { 107 name: "no update taint", 108 args: args{ 109 cnr: &nodeapis.CustomNodeResource{ 110 Spec: nodeapis.CustomNodeResourceSpec{ 111 Taints: []*nodeapis.Taint{ 112 { 113 Key: "test-key", 114 Value: "test-value", 115 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 116 }, 117 }, 118 }, 119 }, 120 taint: &nodeapis.Taint{ 121 Key: "test-key", 122 Value: "test-value", 123 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 124 }, 125 }, 126 want: &nodeapis.CustomNodeResource{ 127 Spec: nodeapis.CustomNodeResourceSpec{ 128 Taints: []*nodeapis.Taint{ 129 { 130 Key: "test-key", 131 Value: "test-value", 132 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 133 }, 134 }, 135 }, 136 }, 137 want1: false, 138 wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { 139 return true 140 }, 141 }, 142 } 143 for _, tt := range tests { 144 tt := tt 145 t.Run(tt.name, func(t *testing.T) { 146 t.Parallel() 147 got, got1, err := AddOrUpdateCNRTaint(tt.args.cnr, tt.args.taint) 148 if !tt.wantErr(t, err, fmt.Sprintf("AddOrUpdateCNRTaint(%v, %v)", tt.args.cnr, tt.args.taint)) { 149 return 150 } 151 assert.Equalf(t, tt.want, got, "AddOrUpdateCNRTaint(%v, %v)", tt.args.cnr, tt.args.taint) 152 assert.Equalf(t, tt.want1, got1, "AddOrUpdateCNRTaint(%v, %v)", tt.args.cnr, tt.args.taint) 153 }) 154 } 155 } 156 157 func TestCNRTaintExists(t *testing.T) { 158 t.Parallel() 159 160 type args struct { 161 taints []*nodeapis.Taint 162 taintToFind *nodeapis.Taint 163 } 164 tests := []struct { 165 name string 166 args args 167 want bool 168 }{ 169 { 170 name: "taint exists", 171 args: args{ 172 taints: []*nodeapis.Taint{ 173 { 174 Key: "test-key", 175 Value: "test-value", 176 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 177 }, 178 }, 179 taintToFind: &nodeapis.Taint{ 180 Key: "test-key", 181 Value: "test-value", 182 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 183 }, 184 }, 185 want: true, 186 }, 187 { 188 name: "taint no exists", 189 args: args{ 190 taints: []*nodeapis.Taint{ 191 { 192 Key: "test-key", 193 Value: "test-value", 194 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 195 }, 196 }, 197 taintToFind: &nodeapis.Taint{ 198 Key: "test-key-1", 199 Value: "test-value-1", 200 Effect: nodeapis.TaintEffectNoScheduleForReclaimedTasks, 201 }, 202 }, 203 want: false, 204 }, 205 } 206 for _, tt := range tests { 207 tt := tt 208 t.Run(tt.name, func(t *testing.T) { 209 t.Parallel() 210 assert.Equalf(t, tt.want, CNRTaintExists(tt.args.taints, tt.args.taintToFind), "CNRTaintExists(%v, %v)", tt.args.taints, tt.args.taintToFind) 211 }) 212 } 213 } 214 215 func TestMergeAllocations(t *testing.T) { 216 t.Parallel() 217 218 type args struct { 219 dst []*nodeapis.Allocation 220 src []*nodeapis.Allocation 221 } 222 tests := []struct { 223 name string 224 args args 225 want []*nodeapis.Allocation 226 }{ 227 { 228 name: "merge all", 229 args: args{ 230 src: []*nodeapis.Allocation{ 231 { 232 Consumer: "aa", 233 Requests: &v1.ResourceList{ 234 v1.ResourceCPU: resource.MustParse("10"), 235 }, 236 }, 237 }, 238 dst: []*nodeapis.Allocation{ 239 { 240 Consumer: "bb", 241 Requests: &v1.ResourceList{ 242 v1.ResourceCPU: resource.MustParse("10"), 243 }, 244 }, 245 }, 246 }, 247 want: []*nodeapis.Allocation{ 248 { 249 Consumer: "aa", 250 Requests: &v1.ResourceList{ 251 v1.ResourceCPU: resource.MustParse("10"), 252 }, 253 }, 254 { 255 Consumer: "bb", 256 Requests: &v1.ResourceList{ 257 v1.ResourceCPU: resource.MustParse("10"), 258 }, 259 }, 260 }, 261 }, 262 { 263 name: "merge resources", 264 args: args{ 265 src: []*nodeapis.Allocation{ 266 { 267 Consumer: "aa", 268 Requests: &v1.ResourceList{ 269 v1.ResourceCPU: resource.MustParse("10"), 270 }, 271 }, 272 }, 273 dst: []*nodeapis.Allocation{ 274 { 275 Consumer: "aa", 276 Requests: &v1.ResourceList{ 277 v1.ResourceMemory: resource.MustParse("10"), 278 }, 279 }, 280 }, 281 }, 282 want: []*nodeapis.Allocation{ 283 { 284 Consumer: "aa", 285 Requests: &v1.ResourceList{ 286 v1.ResourceCPU: resource.MustParse("10"), 287 v1.ResourceMemory: resource.MustParse("10"), 288 }, 289 }, 290 }, 291 }, 292 } 293 for _, tt := range tests { 294 tt := tt 295 t.Run(tt.name, func(t *testing.T) { 296 t.Parallel() 297 assert.Equalf(t, tt.want, MergeAllocations(tt.args.dst, tt.args.src), "MergeAllocations(%v, %v)", tt.args.dst, tt.args.src) 298 }) 299 } 300 } 301 302 func TestMergeAttributes(t *testing.T) { 303 t.Parallel() 304 305 type args struct { 306 dst []nodeapis.Attribute 307 src []nodeapis.Attribute 308 } 309 tests := []struct { 310 name string 311 args args 312 want []nodeapis.Attribute 313 }{ 314 { 315 name: "merge two attribute", 316 args: args{ 317 src: []nodeapis.Attribute{ 318 { 319 Name: "aa", 320 Value: "aa-value", 321 }, 322 }, 323 dst: []nodeapis.Attribute{ 324 { 325 Name: "bb", 326 Value: "bb-value", 327 }, 328 }, 329 }, 330 want: []nodeapis.Attribute{ 331 { 332 Name: "aa", 333 Value: "aa-value", 334 }, 335 { 336 Name: "bb", 337 Value: "bb-value", 338 }, 339 }, 340 }, 341 { 342 name: "merge same attribute", 343 args: args{ 344 src: []nodeapis.Attribute{ 345 { 346 Name: "aa", 347 Value: "aa-value", 348 }, 349 }, 350 dst: []nodeapis.Attribute{ 351 { 352 Name: "aa", 353 Value: "aa-value-1", 354 }, 355 }, 356 }, 357 want: []nodeapis.Attribute{ 358 { 359 Name: "aa", 360 Value: "aa-value-1", 361 }, 362 }, 363 }, 364 } 365 for _, tt := range tests { 366 tt := tt 367 t.Run(tt.name, func(t *testing.T) { 368 t.Parallel() 369 assert.Equalf(t, tt.want, MergeAttributes(tt.args.dst, tt.args.src), "MergeAttributes(%v, %v)", tt.args.dst, tt.args.src) 370 }) 371 } 372 } 373 374 func TestMergeResources(t *testing.T) { 375 t.Parallel() 376 377 type args struct { 378 dst nodeapis.Resources 379 src nodeapis.Resources 380 } 381 tests := []struct { 382 name string 383 args args 384 want nodeapis.Resources 385 }{ 386 { 387 name: "merge capacity and allocatable", 388 args: args{ 389 src: nodeapis.Resources{ 390 Capacity: &v1.ResourceList{ 391 v1.ResourceCPU: resource.MustParse("10"), 392 v1.ResourceMemory: resource.MustParse("10"), 393 }, 394 }, 395 dst: nodeapis.Resources{ 396 Allocatable: &v1.ResourceList{ 397 v1.ResourceCPU: resource.MustParse("10"), 398 v1.ResourceMemory: resource.MustParse("10"), 399 }, 400 }, 401 }, 402 want: nodeapis.Resources{ 403 Capacity: &v1.ResourceList{ 404 v1.ResourceCPU: resource.MustParse("10"), 405 v1.ResourceMemory: resource.MustParse("10"), 406 }, 407 Allocatable: &v1.ResourceList{ 408 v1.ResourceCPU: resource.MustParse("10"), 409 v1.ResourceMemory: resource.MustParse("10"), 410 }, 411 }, 412 }, 413 } 414 for _, tt := range tests { 415 tt := tt 416 t.Run(tt.name, func(t *testing.T) { 417 t.Parallel() 418 assert.Equalf(t, tt.want, MergeResources(tt.args.dst, tt.args.src), "MergeResources(%v, %v)", tt.args.dst, tt.args.src) 419 }) 420 } 421 } 422 423 func TestMergeTopologyZone(t *testing.T) { 424 t.Parallel() 425 426 type args struct { 427 dst []*nodeapis.TopologyZone 428 src []*nodeapis.TopologyZone 429 } 430 tests := []struct { 431 name string 432 args args 433 want []*nodeapis.TopologyZone 434 }{ 435 { 436 name: "merge two topology zone", 437 args: args{ 438 src: []*nodeapis.TopologyZone{ 439 { 440 Type: nodeapis.TopologyTypeSocket, 441 Name: "0", 442 Children: []*nodeapis.TopologyZone{ 443 { 444 Type: nodeapis.TopologyTypeNuma, 445 Name: "0", 446 Resources: nodeapis.Resources{ 447 Capacity: &v1.ResourceList{ 448 "gpu": resource.MustParse("2"), 449 }, 450 Allocatable: &v1.ResourceList{ 451 "gpu": resource.MustParse("2"), 452 }, 453 }, 454 Allocations: []*nodeapis.Allocation{ 455 { 456 Consumer: "default/pod-1/pod-1-uid", 457 Requests: &v1.ResourceList{ 458 "gpu": resource.MustParse("1"), 459 }, 460 }, 461 { 462 Consumer: "default/pod-2/pod-2-uid", 463 Requests: &v1.ResourceList{ 464 "gpu": resource.MustParse("1"), 465 }, 466 }, 467 { 468 Consumer: "default/pod-3/pod-3-uid", 469 Requests: &v1.ResourceList{ 470 "gpu": resource.MustParse("1"), 471 }, 472 }, 473 }, 474 Children: []*nodeapis.TopologyZone{ 475 { 476 Type: nodeapis.TopologyTypeNIC, 477 Name: "eth0", 478 Resources: nodeapis.Resources{ 479 Capacity: &v1.ResourceList{ 480 "nic": resource.MustParse("10G"), 481 }, 482 Allocatable: &v1.ResourceList{ 483 "nic": resource.MustParse("10G"), 484 }, 485 }, 486 Allocations: []*nodeapis.Allocation{ 487 { 488 Consumer: "default/pod-2/pod-2-uid", 489 Requests: &v1.ResourceList{ 490 "nic": resource.MustParse("10G"), 491 }, 492 }, 493 }, 494 }, 495 }, 496 }, 497 }, 498 }, 499 { 500 Type: nodeapis.TopologyTypeSocket, 501 Name: "1", 502 Children: []*nodeapis.TopologyZone{ 503 { 504 Type: nodeapis.TopologyTypeNuma, 505 Name: "1", 506 Resources: nodeapis.Resources{ 507 Capacity: &v1.ResourceList{ 508 "cpu": resource.MustParse("24"), 509 "memory": resource.MustParse("32G"), 510 }, 511 Allocatable: &v1.ResourceList{ 512 "cpu": resource.MustParse("24"), 513 "memory": resource.MustParse("32G"), 514 }, 515 }, 516 Allocations: []*nodeapis.Allocation{ 517 { 518 Consumer: "default/pod-1/pod-1-uid", 519 Requests: &v1.ResourceList{ 520 "cpu": resource.MustParse("15"), 521 "memory": resource.MustParse("15G"), 522 }, 523 }, 524 { 525 Consumer: "default/pod-2/pod-2-uid", 526 Requests: &v1.ResourceList{ 527 "gpu": resource.MustParse("1"), 528 "cpu": resource.MustParse("24"), 529 "memory": resource.MustParse("32G"), 530 }, 531 }, 532 { 533 Consumer: "default/pod-3/pod-3-uid", 534 Requests: &v1.ResourceList{ 535 "gpu": resource.MustParse("1"), 536 "cpu": resource.MustParse("24"), 537 "memory": resource.MustParse("32G"), 538 }, 539 }, 540 }, 541 Children: []*nodeapis.TopologyZone{ 542 { 543 Type: nodeapis.TopologyTypeNIC, 544 Name: "eth1", 545 Resources: nodeapis.Resources{ 546 Capacity: &v1.ResourceList{ 547 "nic": resource.MustParse("10G"), 548 }, 549 Allocatable: &v1.ResourceList{ 550 "nic": resource.MustParse("10G"), 551 }, 552 }, 553 }, 554 }, 555 }, 556 }, 557 }, 558 }, 559 dst: []*nodeapis.TopologyZone{ 560 { 561 Type: nodeapis.TopologyTypeSocket, 562 Name: "0", 563 Children: []*nodeapis.TopologyZone{ 564 { 565 Type: nodeapis.TopologyTypeNuma, 566 Name: "0", 567 Resources: nodeapis.Resources{ 568 Capacity: &v1.ResourceList{ 569 "cpu": resource.MustParse("24"), 570 "memory": resource.MustParse("32G"), 571 }, 572 Allocatable: &v1.ResourceList{ 573 "cpu": resource.MustParse("24"), 574 "memory": resource.MustParse("32G"), 575 }, 576 }, 577 Allocations: []*nodeapis.Allocation{ 578 { 579 Consumer: "default/pod-1/pod-1-uid", 580 Requests: &v1.ResourceList{ 581 "cpu": resource.MustParse("12"), 582 "memory": resource.MustParse("12G"), 583 }, 584 }, 585 { 586 Consumer: "default/pod-2/pod-2-uid", 587 Requests: &v1.ResourceList{ 588 "cpu": resource.MustParse("24"), 589 "memory": resource.MustParse("32G"), 590 }, 591 }, 592 { 593 Consumer: "default/pod-3/pod-3-uid", 594 Requests: &v1.ResourceList{ 595 "cpu": resource.MustParse("24"), 596 "memory": resource.MustParse("32G"), 597 }, 598 }, 599 }, 600 }, 601 }, 602 }, 603 { 604 Type: nodeapis.TopologyTypeSocket, 605 Name: "1", 606 Children: []*nodeapis.TopologyZone{ 607 { 608 Type: nodeapis.TopologyTypeNuma, 609 Name: "1", 610 Resources: nodeapis.Resources{ 611 Capacity: &v1.ResourceList{ 612 "cpu": resource.MustParse("24"), 613 "memory": resource.MustParse("32G"), 614 }, 615 Allocatable: &v1.ResourceList{ 616 "cpu": resource.MustParse("24"), 617 "memory": resource.MustParse("32G"), 618 }, 619 }, 620 Allocations: []*nodeapis.Allocation{ 621 { 622 Consumer: "default/pod-1/pod-1-uid", 623 Requests: &v1.ResourceList{ 624 "cpu": resource.MustParse("15"), 625 "memory": resource.MustParse("15G"), 626 }, 627 }, 628 { 629 Consumer: "default/pod-2/pod-2-uid", 630 Requests: &v1.ResourceList{ 631 "cpu": resource.MustParse("24"), 632 "memory": resource.MustParse("32G"), 633 }, 634 }, 635 { 636 Consumer: "default/pod-3/pod-3-uid", 637 Requests: &v1.ResourceList{ 638 "cpu": resource.MustParse("24"), 639 "memory": resource.MustParse("32G"), 640 }, 641 }, 642 }, 643 }, 644 }, 645 }, 646 }, 647 }, 648 want: []*nodeapis.TopologyZone{ 649 { 650 Type: nodeapis.TopologyTypeSocket, 651 Name: "0", 652 Children: []*nodeapis.TopologyZone{ 653 { 654 Type: nodeapis.TopologyTypeNuma, 655 Name: "0", 656 Resources: nodeapis.Resources{ 657 Capacity: &v1.ResourceList{ 658 "gpu": resource.MustParse("2"), 659 "cpu": resource.MustParse("24"), 660 "memory": resource.MustParse("32G"), 661 }, 662 Allocatable: &v1.ResourceList{ 663 "gpu": resource.MustParse("2"), 664 "cpu": resource.MustParse("24"), 665 "memory": resource.MustParse("32G"), 666 }, 667 }, 668 Allocations: []*nodeapis.Allocation{ 669 { 670 Consumer: "default/pod-1/pod-1-uid", 671 Requests: &v1.ResourceList{ 672 "gpu": resource.MustParse("1"), 673 "cpu": resource.MustParse("12"), 674 "memory": resource.MustParse("12G"), 675 }, 676 }, 677 { 678 Consumer: "default/pod-2/pod-2-uid", 679 Requests: &v1.ResourceList{ 680 "gpu": resource.MustParse("1"), 681 "cpu": resource.MustParse("24"), 682 "memory": resource.MustParse("32G"), 683 }, 684 }, 685 { 686 Consumer: "default/pod-3/pod-3-uid", 687 Requests: &v1.ResourceList{ 688 "gpu": resource.MustParse("1"), 689 "cpu": resource.MustParse("24"), 690 "memory": resource.MustParse("32G"), 691 }, 692 }, 693 }, 694 Children: []*nodeapis.TopologyZone{ 695 { 696 Type: nodeapis.TopologyTypeNIC, 697 Name: "eth0", 698 Resources: nodeapis.Resources{ 699 Capacity: &v1.ResourceList{ 700 "nic": resource.MustParse("10G"), 701 }, 702 Allocatable: &v1.ResourceList{ 703 "nic": resource.MustParse("10G"), 704 }, 705 }, 706 Allocations: []*nodeapis.Allocation{ 707 { 708 Consumer: "default/pod-2/pod-2-uid", 709 Requests: &v1.ResourceList{ 710 "nic": resource.MustParse("10G"), 711 }, 712 }, 713 }, 714 }, 715 }, 716 }, 717 }, 718 }, 719 { 720 Type: nodeapis.TopologyTypeSocket, 721 Name: "1", 722 Children: []*nodeapis.TopologyZone{ 723 { 724 Type: nodeapis.TopologyTypeNuma, 725 Name: "1", 726 Resources: nodeapis.Resources{ 727 Capacity: &v1.ResourceList{ 728 "cpu": resource.MustParse("24"), 729 "memory": resource.MustParse("32G"), 730 }, 731 Allocatable: &v1.ResourceList{ 732 "cpu": resource.MustParse("24"), 733 "memory": resource.MustParse("32G"), 734 }, 735 }, 736 Allocations: []*nodeapis.Allocation{ 737 { 738 Consumer: "default/pod-1/pod-1-uid", 739 Requests: &v1.ResourceList{ 740 "cpu": resource.MustParse("15"), 741 "memory": resource.MustParse("15G"), 742 }, 743 }, 744 { 745 Consumer: "default/pod-2/pod-2-uid", 746 Requests: &v1.ResourceList{ 747 "gpu": resource.MustParse("1"), 748 "cpu": resource.MustParse("24"), 749 "memory": resource.MustParse("32G"), 750 }, 751 }, 752 { 753 Consumer: "default/pod-3/pod-3-uid", 754 Requests: &v1.ResourceList{ 755 "gpu": resource.MustParse("1"), 756 "cpu": resource.MustParse("24"), 757 "memory": resource.MustParse("32G"), 758 }, 759 }, 760 }, 761 Children: []*nodeapis.TopologyZone{ 762 { 763 Type: nodeapis.TopologyTypeNIC, 764 Name: "eth1", 765 Resources: nodeapis.Resources{ 766 Capacity: &v1.ResourceList{ 767 "nic": resource.MustParse("10G"), 768 }, 769 Allocatable: &v1.ResourceList{ 770 "nic": resource.MustParse("10G"), 771 }, 772 }, 773 }, 774 }, 775 }, 776 }, 777 }, 778 }, 779 }, 780 { 781 name: "merge two topology zone with siblings", 782 args: args{ 783 src: []*nodeapis.TopologyZone{ 784 { 785 Type: nodeapis.TopologyTypeSocket, 786 Name: "0", 787 Children: []*nodeapis.TopologyZone{ 788 { 789 Type: nodeapis.TopologyTypeNuma, 790 Name: "0", 791 Resources: nodeapis.Resources{ 792 Capacity: &v1.ResourceList{ 793 "gpu": resource.MustParse("2"), 794 "cpu": resource.MustParse("24"), 795 "memory": resource.MustParse("32G"), 796 }, 797 Allocatable: &v1.ResourceList{ 798 "gpu": resource.MustParse("2"), 799 "cpu": resource.MustParse("24"), 800 "memory": resource.MustParse("32G"), 801 }, 802 }, 803 Allocations: []*nodeapis.Allocation{ 804 { 805 Consumer: "default/pod-1/pod-1-uid", 806 Requests: &v1.ResourceList{ 807 "gpu": resource.MustParse("1"), 808 "cpu": resource.MustParse("12"), 809 "memory": resource.MustParse("12G"), 810 }, 811 }, 812 { 813 Consumer: "default/pod-2/pod-2-uid", 814 Requests: &v1.ResourceList{ 815 "gpu": resource.MustParse("1"), 816 "cpu": resource.MustParse("24"), 817 "memory": resource.MustParse("32G"), 818 }, 819 }, 820 { 821 Consumer: "default/pod-3/pod-3-uid", 822 Requests: &v1.ResourceList{ 823 "gpu": resource.MustParse("1"), 824 "cpu": resource.MustParse("24"), 825 "memory": resource.MustParse("32G"), 826 }, 827 }, 828 }, 829 Children: []*nodeapis.TopologyZone{ 830 { 831 Type: nodeapis.TopologyTypeNIC, 832 Name: "eth0", 833 Resources: nodeapis.Resources{ 834 Capacity: &v1.ResourceList{ 835 "nic": resource.MustParse("10G"), 836 }, 837 Allocatable: &v1.ResourceList{ 838 "nic": resource.MustParse("10G"), 839 }, 840 }, 841 Allocations: []*nodeapis.Allocation{ 842 { 843 Consumer: "default/pod-2/pod-2-uid", 844 Requests: &v1.ResourceList{ 845 "nic": resource.MustParse("10G"), 846 }, 847 }, 848 }, 849 }, 850 }, 851 Siblings: []nodeapis.Sibling{ 852 { 853 Type: nodeapis.TopologyTypeNuma, 854 Name: "1", 855 }, 856 }, 857 }, 858 { 859 Type: nodeapis.TopologyTypeNuma, 860 Name: "1", 861 Resources: nodeapis.Resources{ 862 Capacity: &v1.ResourceList{ 863 "gpu": resource.MustParse("2"), 864 "cpu": resource.MustParse("24"), 865 "memory": resource.MustParse("32G"), 866 }, 867 Allocatable: &v1.ResourceList{ 868 "gpu": resource.MustParse("2"), 869 "cpu": resource.MustParse("24"), 870 "memory": resource.MustParse("32G"), 871 }, 872 }, 873 Allocations: []*nodeapis.Allocation{ 874 { 875 Consumer: "default/pod-1/pod-1-uid", 876 Requests: &v1.ResourceList{ 877 "gpu": resource.MustParse("1"), 878 "cpu": resource.MustParse("12"), 879 "memory": resource.MustParse("12G"), 880 }, 881 }, 882 { 883 Consumer: "default/pod-2/pod-2-uid", 884 Requests: &v1.ResourceList{ 885 "gpu": resource.MustParse("1"), 886 "cpu": resource.MustParse("24"), 887 "memory": resource.MustParse("32G"), 888 }, 889 }, 890 { 891 Consumer: "default/pod-3/pod-3-uid", 892 Requests: &v1.ResourceList{ 893 "gpu": resource.MustParse("1"), 894 "cpu": resource.MustParse("24"), 895 "memory": resource.MustParse("32G"), 896 }, 897 }, 898 }, 899 Children: []*nodeapis.TopologyZone{ 900 { 901 Type: nodeapis.TopologyTypeNIC, 902 Name: "eth0", 903 Resources: nodeapis.Resources{ 904 Capacity: &v1.ResourceList{ 905 "nic": resource.MustParse("10G"), 906 }, 907 Allocatable: &v1.ResourceList{ 908 "nic": resource.MustParse("10G"), 909 }, 910 }, 911 Allocations: []*nodeapis.Allocation{ 912 { 913 Consumer: "default/pod-2/pod-2-uid", 914 Requests: &v1.ResourceList{ 915 "nic": resource.MustParse("10G"), 916 }, 917 }, 918 }, 919 }, 920 }, 921 Siblings: []nodeapis.Sibling{ 922 { 923 Type: nodeapis.TopologyTypeNuma, 924 Name: "0", 925 }, 926 }, 927 }, 928 }, 929 }, 930 { 931 Type: nodeapis.TopologyTypeSocket, 932 Name: "1", 933 Children: []*nodeapis.TopologyZone{ 934 { 935 Type: nodeapis.TopologyTypeNuma, 936 Name: "2", 937 Resources: nodeapis.Resources{ 938 Capacity: &v1.ResourceList{ 939 "cpu": resource.MustParse("24"), 940 "memory": resource.MustParse("32G"), 941 }, 942 Allocatable: &v1.ResourceList{ 943 "cpu": resource.MustParse("24"), 944 "memory": resource.MustParse("32G"), 945 }, 946 }, 947 Allocations: []*nodeapis.Allocation{ 948 { 949 Consumer: "default/pod-1/pod-1-uid", 950 Requests: &v1.ResourceList{ 951 "cpu": resource.MustParse("15"), 952 "memory": resource.MustParse("15G"), 953 }, 954 }, 955 { 956 Consumer: "default/pod-2/pod-2-uid", 957 Requests: &v1.ResourceList{ 958 "gpu": resource.MustParse("1"), 959 "cpu": resource.MustParse("24"), 960 "memory": resource.MustParse("32G"), 961 }, 962 }, 963 { 964 Consumer: "default/pod-3/pod-3-uid", 965 Requests: &v1.ResourceList{ 966 "gpu": resource.MustParse("1"), 967 "cpu": resource.MustParse("24"), 968 "memory": resource.MustParse("32G"), 969 }, 970 }, 971 }, 972 Children: []*nodeapis.TopologyZone{ 973 { 974 Type: nodeapis.TopologyTypeNIC, 975 Name: "eth1", 976 Resources: nodeapis.Resources{ 977 Capacity: &v1.ResourceList{ 978 "nic": resource.MustParse("10G"), 979 }, 980 Allocatable: &v1.ResourceList{ 981 "nic": resource.MustParse("10G"), 982 }, 983 }, 984 }, 985 }, 986 Siblings: []nodeapis.Sibling{ 987 { 988 Type: nodeapis.TopologyTypeNuma, 989 Name: "3", 990 }, 991 }, 992 }, 993 { 994 Type: nodeapis.TopologyTypeNuma, 995 Name: "3", 996 Resources: nodeapis.Resources{ 997 Capacity: &v1.ResourceList{ 998 "cpu": resource.MustParse("24"), 999 "memory": resource.MustParse("32G"), 1000 }, 1001 Allocatable: &v1.ResourceList{ 1002 "cpu": resource.MustParse("24"), 1003 "memory": resource.MustParse("32G"), 1004 }, 1005 }, 1006 Allocations: []*nodeapis.Allocation{ 1007 { 1008 Consumer: "default/pod-1/pod-1-uid", 1009 Requests: &v1.ResourceList{ 1010 "cpu": resource.MustParse("15"), 1011 "memory": resource.MustParse("15G"), 1012 }, 1013 }, 1014 { 1015 Consumer: "default/pod-2/pod-2-uid", 1016 Requests: &v1.ResourceList{ 1017 "gpu": resource.MustParse("1"), 1018 "cpu": resource.MustParse("24"), 1019 "memory": resource.MustParse("32G"), 1020 }, 1021 }, 1022 { 1023 Consumer: "default/pod-3/pod-3-uid", 1024 Requests: &v1.ResourceList{ 1025 "gpu": resource.MustParse("1"), 1026 "cpu": resource.MustParse("24"), 1027 "memory": resource.MustParse("32G"), 1028 }, 1029 }, 1030 }, 1031 Children: []*nodeapis.TopologyZone{ 1032 { 1033 Type: nodeapis.TopologyTypeNIC, 1034 Name: "eth1", 1035 Resources: nodeapis.Resources{ 1036 Capacity: &v1.ResourceList{ 1037 "nic": resource.MustParse("10G"), 1038 }, 1039 Allocatable: &v1.ResourceList{ 1040 "nic": resource.MustParse("10G"), 1041 }, 1042 }, 1043 }, 1044 }, 1045 Siblings: []nodeapis.Sibling{ 1046 { 1047 Type: nodeapis.TopologyTypeNuma, 1048 Name: "2", 1049 }, 1050 }, 1051 }, 1052 }, 1053 }, 1054 }, 1055 dst: []*nodeapis.TopologyZone{ 1056 { 1057 Type: nodeapis.TopologyTypeSocket, 1058 Name: "0", 1059 Children: []*nodeapis.TopologyZone{ 1060 { 1061 Type: nodeapis.TopologyTypeNuma, 1062 Name: "0", 1063 Siblings: []nodeapis.Sibling{ 1064 { 1065 Type: nodeapis.TopologyTypeNuma, 1066 Name: "1", 1067 Attributes: []nodeapis.Attribute{ 1068 { 1069 Name: "aa", 1070 Value: "bb", 1071 }, 1072 }, 1073 }, 1074 }, 1075 }, 1076 { 1077 Type: nodeapis.TopologyTypeNuma, 1078 Name: "1", 1079 Siblings: []nodeapis.Sibling{ 1080 { 1081 Type: nodeapis.TopologyTypeNuma, 1082 Name: "0", 1083 Attributes: []nodeapis.Attribute{ 1084 { 1085 Name: "aa", 1086 Value: "bb", 1087 }, 1088 }, 1089 }, 1090 }, 1091 }, 1092 }, 1093 }, 1094 { 1095 Type: nodeapis.TopologyTypeSocket, 1096 Name: "1", 1097 Children: []*nodeapis.TopologyZone{ 1098 { 1099 Type: nodeapis.TopologyTypeNuma, 1100 Name: "2", 1101 Siblings: []nodeapis.Sibling{ 1102 { 1103 Type: nodeapis.TopologyTypeNuma, 1104 Name: "3", 1105 Attributes: []nodeapis.Attribute{ 1106 { 1107 Name: "aa", 1108 Value: "bb", 1109 }, 1110 }, 1111 }, 1112 }, 1113 }, 1114 { 1115 Type: nodeapis.TopologyTypeNuma, 1116 Name: "3", 1117 Siblings: []nodeapis.Sibling{ 1118 { 1119 Type: nodeapis.TopologyTypeNuma, 1120 Name: "2", 1121 Attributes: []nodeapis.Attribute{ 1122 { 1123 Name: "aa", 1124 Value: "bb", 1125 }, 1126 }, 1127 }, 1128 }, 1129 }, 1130 }, 1131 }, 1132 }, 1133 }, 1134 want: []*nodeapis.TopologyZone{ 1135 { 1136 Type: nodeapis.TopologyTypeSocket, 1137 Name: "0", 1138 Children: []*nodeapis.TopologyZone{ 1139 { 1140 Type: nodeapis.TopologyTypeNuma, 1141 Name: "0", 1142 Resources: nodeapis.Resources{ 1143 Capacity: &v1.ResourceList{ 1144 "gpu": resource.MustParse("2"), 1145 "cpu": resource.MustParse("24"), 1146 "memory": resource.MustParse("32G"), 1147 }, 1148 Allocatable: &v1.ResourceList{ 1149 "gpu": resource.MustParse("2"), 1150 "cpu": resource.MustParse("24"), 1151 "memory": resource.MustParse("32G"), 1152 }, 1153 }, 1154 Allocations: []*nodeapis.Allocation{ 1155 { 1156 Consumer: "default/pod-1/pod-1-uid", 1157 Requests: &v1.ResourceList{ 1158 "gpu": resource.MustParse("1"), 1159 "cpu": resource.MustParse("12"), 1160 "memory": resource.MustParse("12G"), 1161 }, 1162 }, 1163 { 1164 Consumer: "default/pod-2/pod-2-uid", 1165 Requests: &v1.ResourceList{ 1166 "gpu": resource.MustParse("1"), 1167 "cpu": resource.MustParse("24"), 1168 "memory": resource.MustParse("32G"), 1169 }, 1170 }, 1171 { 1172 Consumer: "default/pod-3/pod-3-uid", 1173 Requests: &v1.ResourceList{ 1174 "gpu": resource.MustParse("1"), 1175 "cpu": resource.MustParse("24"), 1176 "memory": resource.MustParse("32G"), 1177 }, 1178 }, 1179 }, 1180 Children: []*nodeapis.TopologyZone{ 1181 { 1182 Type: nodeapis.TopologyTypeNIC, 1183 Name: "eth0", 1184 Resources: nodeapis.Resources{ 1185 Capacity: &v1.ResourceList{ 1186 "nic": resource.MustParse("10G"), 1187 }, 1188 Allocatable: &v1.ResourceList{ 1189 "nic": resource.MustParse("10G"), 1190 }, 1191 }, 1192 Allocations: []*nodeapis.Allocation{ 1193 { 1194 Consumer: "default/pod-2/pod-2-uid", 1195 Requests: &v1.ResourceList{ 1196 "nic": resource.MustParse("10G"), 1197 }, 1198 }, 1199 }, 1200 }, 1201 }, 1202 Siblings: []nodeapis.Sibling{ 1203 { 1204 Type: nodeapis.TopologyTypeNuma, 1205 Name: "1", 1206 Attributes: []nodeapis.Attribute{ 1207 { 1208 Name: "aa", 1209 Value: "bb", 1210 }, 1211 }, 1212 }, 1213 }, 1214 }, 1215 { 1216 Type: nodeapis.TopologyTypeNuma, 1217 Name: "1", 1218 Resources: nodeapis.Resources{ 1219 Capacity: &v1.ResourceList{ 1220 "gpu": resource.MustParse("2"), 1221 "cpu": resource.MustParse("24"), 1222 "memory": resource.MustParse("32G"), 1223 }, 1224 Allocatable: &v1.ResourceList{ 1225 "gpu": resource.MustParse("2"), 1226 "cpu": resource.MustParse("24"), 1227 "memory": resource.MustParse("32G"), 1228 }, 1229 }, 1230 Allocations: []*nodeapis.Allocation{ 1231 { 1232 Consumer: "default/pod-1/pod-1-uid", 1233 Requests: &v1.ResourceList{ 1234 "gpu": resource.MustParse("1"), 1235 "cpu": resource.MustParse("12"), 1236 "memory": resource.MustParse("12G"), 1237 }, 1238 }, 1239 { 1240 Consumer: "default/pod-2/pod-2-uid", 1241 Requests: &v1.ResourceList{ 1242 "gpu": resource.MustParse("1"), 1243 "cpu": resource.MustParse("24"), 1244 "memory": resource.MustParse("32G"), 1245 }, 1246 }, 1247 { 1248 Consumer: "default/pod-3/pod-3-uid", 1249 Requests: &v1.ResourceList{ 1250 "gpu": resource.MustParse("1"), 1251 "cpu": resource.MustParse("24"), 1252 "memory": resource.MustParse("32G"), 1253 }, 1254 }, 1255 }, 1256 Children: []*nodeapis.TopologyZone{ 1257 { 1258 Type: nodeapis.TopologyTypeNIC, 1259 Name: "eth0", 1260 Resources: nodeapis.Resources{ 1261 Capacity: &v1.ResourceList{ 1262 "nic": resource.MustParse("10G"), 1263 }, 1264 Allocatable: &v1.ResourceList{ 1265 "nic": resource.MustParse("10G"), 1266 }, 1267 }, 1268 Allocations: []*nodeapis.Allocation{ 1269 { 1270 Consumer: "default/pod-2/pod-2-uid", 1271 Requests: &v1.ResourceList{ 1272 "nic": resource.MustParse("10G"), 1273 }, 1274 }, 1275 }, 1276 }, 1277 }, 1278 Siblings: []nodeapis.Sibling{ 1279 { 1280 Type: nodeapis.TopologyTypeNuma, 1281 Name: "0", 1282 Attributes: []nodeapis.Attribute{ 1283 { 1284 Name: "aa", 1285 Value: "bb", 1286 }, 1287 }, 1288 }, 1289 }, 1290 }, 1291 }, 1292 }, 1293 { 1294 Type: nodeapis.TopologyTypeSocket, 1295 Name: "1", 1296 Children: []*nodeapis.TopologyZone{ 1297 { 1298 Type: nodeapis.TopologyTypeNuma, 1299 Name: "2", 1300 Resources: nodeapis.Resources{ 1301 Capacity: &v1.ResourceList{ 1302 "cpu": resource.MustParse("24"), 1303 "memory": resource.MustParse("32G"), 1304 }, 1305 Allocatable: &v1.ResourceList{ 1306 "cpu": resource.MustParse("24"), 1307 "memory": resource.MustParse("32G"), 1308 }, 1309 }, 1310 Allocations: []*nodeapis.Allocation{ 1311 { 1312 Consumer: "default/pod-1/pod-1-uid", 1313 Requests: &v1.ResourceList{ 1314 "cpu": resource.MustParse("15"), 1315 "memory": resource.MustParse("15G"), 1316 }, 1317 }, 1318 { 1319 Consumer: "default/pod-2/pod-2-uid", 1320 Requests: &v1.ResourceList{ 1321 "gpu": resource.MustParse("1"), 1322 "cpu": resource.MustParse("24"), 1323 "memory": resource.MustParse("32G"), 1324 }, 1325 }, 1326 { 1327 Consumer: "default/pod-3/pod-3-uid", 1328 Requests: &v1.ResourceList{ 1329 "gpu": resource.MustParse("1"), 1330 "cpu": resource.MustParse("24"), 1331 "memory": resource.MustParse("32G"), 1332 }, 1333 }, 1334 }, 1335 Children: []*nodeapis.TopologyZone{ 1336 { 1337 Type: nodeapis.TopologyTypeNIC, 1338 Name: "eth1", 1339 Resources: nodeapis.Resources{ 1340 Capacity: &v1.ResourceList{ 1341 "nic": resource.MustParse("10G"), 1342 }, 1343 Allocatable: &v1.ResourceList{ 1344 "nic": resource.MustParse("10G"), 1345 }, 1346 }, 1347 }, 1348 }, 1349 Siblings: []nodeapis.Sibling{ 1350 { 1351 Type: nodeapis.TopologyTypeNuma, 1352 Name: "3", 1353 Attributes: []nodeapis.Attribute{ 1354 { 1355 Name: "aa", 1356 Value: "bb", 1357 }, 1358 }, 1359 }, 1360 }, 1361 }, 1362 { 1363 Type: nodeapis.TopologyTypeNuma, 1364 Name: "3", 1365 Resources: nodeapis.Resources{ 1366 Capacity: &v1.ResourceList{ 1367 "cpu": resource.MustParse("24"), 1368 "memory": resource.MustParse("32G"), 1369 }, 1370 Allocatable: &v1.ResourceList{ 1371 "cpu": resource.MustParse("24"), 1372 "memory": resource.MustParse("32G"), 1373 }, 1374 }, 1375 Allocations: []*nodeapis.Allocation{ 1376 { 1377 Consumer: "default/pod-1/pod-1-uid", 1378 Requests: &v1.ResourceList{ 1379 "cpu": resource.MustParse("15"), 1380 "memory": resource.MustParse("15G"), 1381 }, 1382 }, 1383 { 1384 Consumer: "default/pod-2/pod-2-uid", 1385 Requests: &v1.ResourceList{ 1386 "gpu": resource.MustParse("1"), 1387 "cpu": resource.MustParse("24"), 1388 "memory": resource.MustParse("32G"), 1389 }, 1390 }, 1391 { 1392 Consumer: "default/pod-3/pod-3-uid", 1393 Requests: &v1.ResourceList{ 1394 "gpu": resource.MustParse("1"), 1395 "cpu": resource.MustParse("24"), 1396 "memory": resource.MustParse("32G"), 1397 }, 1398 }, 1399 }, 1400 Children: []*nodeapis.TopologyZone{ 1401 { 1402 Type: nodeapis.TopologyTypeNIC, 1403 Name: "eth1", 1404 Resources: nodeapis.Resources{ 1405 Capacity: &v1.ResourceList{ 1406 "nic": resource.MustParse("10G"), 1407 }, 1408 Allocatable: &v1.ResourceList{ 1409 "nic": resource.MustParse("10G"), 1410 }, 1411 }, 1412 }, 1413 }, 1414 Siblings: []nodeapis.Sibling{ 1415 { 1416 Type: nodeapis.TopologyTypeNuma, 1417 Name: "2", 1418 Attributes: []nodeapis.Attribute{ 1419 { 1420 Name: "aa", 1421 Value: "bb", 1422 }, 1423 }, 1424 }, 1425 }, 1426 }, 1427 }, 1428 }, 1429 }, 1430 }, 1431 } 1432 for _, tt := range tests { 1433 tt := tt 1434 t.Run(tt.name, func(t *testing.T) { 1435 t.Parallel() 1436 expect := MergeTopologyZone(tt.args.dst, tt.args.src) 1437 assert.Equalf(t, tt.want, expect, "MergeTopologyZone(%v, %v)", tt.args.dst, tt.args.src) 1438 }) 1439 } 1440 }