agones.dev/agones@v1.54.0/pkg/allocation/converters/converter_test.go (about) 1 // Copyright 2019 Google LLC All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package converters 16 17 import ( 18 "fmt" 19 "testing" 20 21 "github.com/stretchr/testify/assert" 22 "github.com/stretchr/testify/require" 23 "google.golang.org/grpc/codes" 24 "google.golang.org/grpc/status" 25 "google.golang.org/protobuf/types/known/wrapperspb" 26 corev1 "k8s.io/api/core/v1" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 29 pb "agones.dev/agones/pkg/allocation/go" 30 "agones.dev/agones/pkg/apis" 31 agonesv1 "agones.dev/agones/pkg/apis/agones/v1" 32 allocationv1 "agones.dev/agones/pkg/apis/allocation/v1" 33 "agones.dev/agones/pkg/util/runtime" 34 ) 35 36 func TestConvertAllocationRequestToGameServerAllocation(t *testing.T) { 37 allocated := agonesv1.GameServerStateAllocated 38 ready := agonesv1.GameServerStateReady 39 increment := agonesv1.GameServerPriorityIncrement 40 decrement := agonesv1.GameServerPriorityDecrement 41 one := int64(1) 42 ten := int64(10) 43 44 tests := []struct { 45 name string 46 features string 47 in *pb.AllocationRequest 48 want *allocationv1.GameServerAllocation 49 }{ 50 { 51 name: "all fields are set (PlayerAllocationFilter, CountsAndListsFilter)", 52 features: fmt.Sprintf("%s=true&%s=true", runtime.FeaturePlayerAllocationFilter, runtime.FeatureCountsAndLists), 53 in: &pb.AllocationRequest{ 54 Namespace: "ns", 55 MultiClusterSetting: &pb.MultiClusterSetting{ 56 Enabled: true, 57 PolicySelector: &pb.LabelSelector{ 58 MatchLabels: map[string]string{ 59 "a": "b", 60 }, 61 }, 62 }, 63 RequiredGameServerSelector: &pb.GameServerSelector{ 64 MatchLabels: map[string]string{ 65 "c": "d", 66 }, 67 GameServerState: pb.GameServerSelector_READY, 68 Players: &pb.PlayerSelector{ 69 MinAvailable: 10, 70 MaxAvailable: 20, 71 }, 72 }, 73 PreferredGameServerSelectors: []*pb.GameServerSelector{ 74 { 75 MatchLabels: map[string]string{ 76 "e": "f", 77 }, 78 GameServerState: pb.GameServerSelector_ALLOCATED, 79 Players: &pb.PlayerSelector{ 80 MinAvailable: 5, 81 MaxAvailable: 10, 82 }, 83 }, 84 { 85 MatchLabels: map[string]string{ 86 "g": "h", 87 }, 88 }, 89 }, 90 GameServerSelectors: []*pb.GameServerSelector{ 91 { 92 MatchLabels: map[string]string{ 93 "m": "n", 94 }, 95 GameServerState: pb.GameServerSelector_READY, 96 Counters: map[string]*pb.CounterSelector{ 97 "o": { 98 MinCount: 0, 99 MaxCount: 10, 100 MinAvailable: 1, 101 MaxAvailable: 10, 102 }, 103 }, 104 Lists: map[string]*pb.ListSelector{ 105 "p": { 106 ContainsValue: "abc", 107 MinAvailable: 1, 108 MaxAvailable: 10, 109 }, 110 }, 111 }, 112 }, 113 Priorities: []*pb.Priority{ 114 { 115 Type: pb.Priority_Counter, 116 Key: "o", 117 Order: pb.Priority_Descending, 118 }, 119 { 120 Type: pb.Priority_List, 121 Key: "p", 122 Order: pb.Priority_Ascending, 123 }, 124 }, 125 Counters: map[string]*pb.CounterAction{ 126 "o": { 127 Action: wrapperspb.String("Increment"), 128 Amount: wrapperspb.Int64(1), 129 }, 130 "q": { 131 Action: wrapperspb.String("Decrement"), 132 Amount: wrapperspb.Int64(1), 133 Capacity: wrapperspb.Int64(10), 134 }, 135 }, 136 Lists: map[string]*pb.ListAction{ 137 "p": { 138 AddValues: []string{"foo", "bar", "baz"}, 139 Capacity: wrapperspb.Int64(10), 140 DeleteValues: []string{"alice", "bob", "cat"}, 141 }, 142 }, 143 Scheduling: pb.AllocationRequest_Packed, 144 Metadata: &pb.MetaPatch{ 145 Labels: map[string]string{ 146 "i": "j", 147 }, 148 }, 149 MetaPatch: &pb.MetaPatch{ 150 Labels: map[string]string{ 151 "i": "j", 152 }, 153 }, 154 }, 155 want: &allocationv1.GameServerAllocation{ 156 ObjectMeta: metav1.ObjectMeta{ 157 Namespace: "ns", 158 }, 159 Spec: allocationv1.GameServerAllocationSpec{ 160 MultiClusterSetting: allocationv1.MultiClusterSetting{ 161 Enabled: true, 162 PolicySelector: metav1.LabelSelector{ 163 MatchLabels: map[string]string{ 164 "a": "b", 165 }, 166 }, 167 }, 168 Required: allocationv1.GameServerSelector{ 169 LabelSelector: metav1.LabelSelector{ 170 MatchLabels: map[string]string{ 171 "c": "d", 172 }, 173 }, 174 GameServerState: &ready, 175 Players: &allocationv1.PlayerSelector{MinAvailable: 10, MaxAvailable: 20}, 176 }, 177 Preferred: []allocationv1.GameServerSelector{ 178 { 179 LabelSelector: metav1.LabelSelector{ 180 MatchLabels: map[string]string{ 181 "e": "f", 182 }, 183 }, 184 GameServerState: &allocated, 185 Players: &allocationv1.PlayerSelector{MinAvailable: 5, MaxAvailable: 10}, 186 }, 187 { 188 LabelSelector: metav1.LabelSelector{ 189 MatchLabels: map[string]string{ 190 "g": "h", 191 }, 192 }, 193 GameServerState: &ready, 194 }, 195 }, 196 Priorities: []agonesv1.Priority{ 197 { 198 Type: "Counter", 199 Key: "o", 200 Order: "Descending", 201 }, 202 { 203 Type: "List", 204 Key: "p", 205 Order: "Ascending", 206 }, 207 }, 208 Counters: map[string]allocationv1.CounterAction{ 209 "o": { 210 Action: &increment, 211 Amount: &one, 212 }, 213 "q": { 214 Action: &decrement, 215 Amount: &one, 216 Capacity: &ten, 217 }, 218 }, 219 Lists: map[string]allocationv1.ListAction{ 220 "p": { 221 AddValues: []string{"foo", "bar", "baz"}, 222 Capacity: &ten, 223 DeleteValues: []string{"alice", "bob", "cat"}, 224 }, 225 }, 226 Selectors: []allocationv1.GameServerSelector{ 227 { 228 LabelSelector: metav1.LabelSelector{ 229 MatchLabels: map[string]string{ 230 "m": "n", 231 }, 232 }, 233 GameServerState: &ready, 234 Counters: map[string]allocationv1.CounterSelector{ 235 "o": { 236 MinCount: 0, 237 MaxCount: 10, 238 MinAvailable: 1, 239 MaxAvailable: 10, 240 }, 241 }, 242 Lists: map[string]allocationv1.ListSelector{ 243 "p": { 244 ContainsValue: "abc", 245 MinAvailable: 1, 246 MaxAvailable: 10, 247 }, 248 }, 249 }, 250 }, 251 Scheduling: apis.Packed, 252 MetaPatch: allocationv1.MetaPatch{ 253 Labels: map[string]string{ 254 "i": "j", 255 }, 256 }, 257 }, 258 }, 259 }, 260 { 261 name: "all fields are set", 262 features: fmt.Sprintf("%s=false&%s=false", runtime.FeaturePlayerAllocationFilter, runtime.FeatureCountsAndLists), 263 in: &pb.AllocationRequest{ 264 Namespace: "ns", 265 MultiClusterSetting: &pb.MultiClusterSetting{ 266 Enabled: true, 267 PolicySelector: &pb.LabelSelector{ 268 MatchLabels: map[string]string{ 269 "a": "b", 270 }, 271 }, 272 }, 273 RequiredGameServerSelector: &pb.GameServerSelector{ 274 MatchLabels: map[string]string{ 275 "c": "d", 276 }, 277 }, 278 PreferredGameServerSelectors: []*pb.GameServerSelector{ 279 { 280 MatchLabels: map[string]string{ 281 "e": "f", 282 }, 283 }, 284 { 285 MatchLabels: map[string]string{ 286 "g": "h", 287 }, 288 }, 289 }, 290 GameServerSelectors: []*pb.GameServerSelector{ 291 { 292 MatchLabels: map[string]string{ 293 "m": "n", 294 }, 295 }, 296 }, 297 Scheduling: pb.AllocationRequest_Packed, 298 Metadata: &pb.MetaPatch{ 299 Labels: map[string]string{ 300 "i": "j", 301 }, 302 }, 303 MetaPatch: &pb.MetaPatch{ 304 Labels: map[string]string{ 305 "i": "j", 306 }, 307 }, 308 }, 309 want: &allocationv1.GameServerAllocation{ 310 ObjectMeta: metav1.ObjectMeta{ 311 Namespace: "ns", 312 }, 313 Spec: allocationv1.GameServerAllocationSpec{ 314 MultiClusterSetting: allocationv1.MultiClusterSetting{ 315 Enabled: true, 316 PolicySelector: metav1.LabelSelector{ 317 MatchLabels: map[string]string{ 318 "a": "b", 319 }, 320 }, 321 }, 322 Required: allocationv1.GameServerSelector{LabelSelector: metav1.LabelSelector{ 323 MatchLabels: map[string]string{ 324 "c": "d", 325 }, 326 }, 327 GameServerState: &ready, 328 }, 329 Preferred: []allocationv1.GameServerSelector{ 330 { 331 LabelSelector: metav1.LabelSelector{ 332 MatchLabels: map[string]string{ 333 "e": "f", 334 }, 335 }, 336 GameServerState: &ready, 337 }, 338 { 339 LabelSelector: metav1.LabelSelector{ 340 MatchLabels: map[string]string{ 341 "g": "h", 342 }, 343 }, 344 GameServerState: &ready, 345 }, 346 }, 347 Selectors: []allocationv1.GameServerSelector{ 348 { 349 LabelSelector: metav1.LabelSelector{ 350 MatchLabels: map[string]string{ 351 "m": "n", 352 }, 353 }, 354 GameServerState: &ready, 355 }, 356 }, 357 Scheduling: apis.Packed, 358 MetaPatch: allocationv1.MetaPatch{ 359 Labels: map[string]string{ 360 "i": "j", 361 }, 362 }, 363 }, 364 }, 365 }, 366 { 367 name: "empty fields to GSA", 368 features: fmt.Sprintf("%s=false&%s=false", runtime.FeaturePlayerAllocationFilter, runtime.FeatureCountsAndLists), 369 in: &pb.AllocationRequest{ 370 Namespace: "", 371 MultiClusterSetting: &pb.MultiClusterSetting{}, 372 RequiredGameServerSelector: &pb.GameServerSelector{}, 373 PreferredGameServerSelectors: []*pb.GameServerSelector{}, 374 Scheduling: pb.AllocationRequest_Distributed, 375 Metadata: &pb.MetaPatch{}, 376 }, 377 want: &allocationv1.GameServerAllocation{ 378 ObjectMeta: metav1.ObjectMeta{ 379 Namespace: "", 380 }, 381 Spec: allocationv1.GameServerAllocationSpec{ 382 MultiClusterSetting: allocationv1.MultiClusterSetting{ 383 Enabled: false, 384 }, 385 Scheduling: apis.Distributed, 386 Required: allocationv1.GameServerSelector{ 387 GameServerState: &ready, 388 }, 389 }, 390 }, 391 }, 392 { 393 name: "empty fields to GSA (PlayerAllocationFilter, CountsAndListsFilter)", 394 features: fmt.Sprintf("%s=true&%s=true", runtime.FeaturePlayerAllocationFilter, runtime.FeatureCountsAndLists), 395 in: &pb.AllocationRequest{ 396 Namespace: "", 397 MultiClusterSetting: &pb.MultiClusterSetting{}, 398 RequiredGameServerSelector: &pb.GameServerSelector{}, 399 PreferredGameServerSelectors: []*pb.GameServerSelector{}, 400 Scheduling: pb.AllocationRequest_Distributed, 401 Metadata: &pb.MetaPatch{}, 402 }, 403 want: &allocationv1.GameServerAllocation{ 404 ObjectMeta: metav1.ObjectMeta{ 405 Namespace: "", 406 }, 407 Spec: allocationv1.GameServerAllocationSpec{ 408 MultiClusterSetting: allocationv1.MultiClusterSetting{ 409 Enabled: false, 410 }, 411 Required: allocationv1.GameServerSelector{ 412 GameServerState: &ready, 413 }, 414 Scheduling: apis.Distributed, 415 }, 416 }, 417 }, 418 { 419 name: "empty fields to GSA with selectors fields", 420 features: fmt.Sprintf("%s=false&%s=false", runtime.FeaturePlayerAllocationFilter, runtime.FeatureCountsAndLists), 421 in: &pb.AllocationRequest{ 422 Namespace: "", 423 MultiClusterSetting: &pb.MultiClusterSetting{}, 424 GameServerSelectors: []*pb.GameServerSelector{{}}, 425 Scheduling: pb.AllocationRequest_Distributed, 426 Metadata: &pb.MetaPatch{}, 427 }, 428 want: &allocationv1.GameServerAllocation{ 429 ObjectMeta: metav1.ObjectMeta{ 430 Namespace: "", 431 }, 432 Spec: allocationv1.GameServerAllocationSpec{ 433 MultiClusterSetting: allocationv1.MultiClusterSetting{ 434 Enabled: false, 435 }, 436 Selectors: []allocationv1.GameServerSelector{{ 437 GameServerState: &ready, 438 }}, 439 Scheduling: apis.Distributed, 440 }, 441 }, 442 }, 443 { 444 name: "empty fields to GSA (PlayerAllocationFilter, CountsAndListsFilter) with selectors fields", 445 features: fmt.Sprintf("%s=true&%s=true", runtime.FeaturePlayerAllocationFilter, runtime.FeatureCountsAndLists), 446 in: &pb.AllocationRequest{ 447 Namespace: "", 448 MultiClusterSetting: &pb.MultiClusterSetting{}, 449 GameServerSelectors: []*pb.GameServerSelector{{}}, 450 Scheduling: pb.AllocationRequest_Distributed, 451 Metadata: &pb.MetaPatch{}, 452 }, 453 want: &allocationv1.GameServerAllocation{ 454 ObjectMeta: metav1.ObjectMeta{ 455 Namespace: "", 456 }, 457 Spec: allocationv1.GameServerAllocationSpec{ 458 MultiClusterSetting: allocationv1.MultiClusterSetting{ 459 Enabled: false, 460 }, 461 Selectors: []allocationv1.GameServerSelector{ 462 {GameServerState: &ready}, 463 }, 464 Scheduling: apis.Distributed, 465 }, 466 }, 467 }, 468 { 469 name: "empty object to GSA", 470 in: &pb.AllocationRequest{}, 471 want: &allocationv1.GameServerAllocation{ 472 Spec: allocationv1.GameServerAllocationSpec{ 473 Scheduling: apis.Packed, 474 }, 475 }, 476 }, 477 { 478 name: "nil object", 479 in: nil, 480 want: nil, 481 }, 482 { 483 name: "accepts deprecated metapatch field", 484 in: &pb.AllocationRequest{ 485 Namespace: "", 486 MultiClusterSetting: &pb.MultiClusterSetting{}, 487 RequiredGameServerSelector: &pb.GameServerSelector{}, 488 PreferredGameServerSelectors: []*pb.GameServerSelector{}, 489 Scheduling: pb.AllocationRequest_Distributed, 490 MetaPatch: &pb.MetaPatch{ 491 Labels: map[string]string{ 492 "a": "b", 493 }, 494 }, 495 }, 496 want: &allocationv1.GameServerAllocation{ 497 ObjectMeta: metav1.ObjectMeta{ 498 Namespace: "", 499 }, 500 Spec: allocationv1.GameServerAllocationSpec{ 501 MultiClusterSetting: allocationv1.MultiClusterSetting{ 502 Enabled: false, 503 }, 504 Required: allocationv1.GameServerSelector{ 505 GameServerState: &ready, 506 }, 507 Scheduling: apis.Distributed, 508 MetaPatch: allocationv1.MetaPatch{ 509 Labels: map[string]string{ 510 "a": "b", 511 }, 512 }, 513 }, 514 }, 515 }, 516 { 517 name: "Prefers metadata over metapatch field", 518 in: &pb.AllocationRequest{ 519 Namespace: "", 520 MultiClusterSetting: &pb.MultiClusterSetting{}, 521 RequiredGameServerSelector: &pb.GameServerSelector{}, 522 PreferredGameServerSelectors: []*pb.GameServerSelector{}, 523 Scheduling: pb.AllocationRequest_Distributed, 524 Metadata: &pb.MetaPatch{ 525 Labels: map[string]string{ 526 "a": "b", 527 }, 528 }, 529 MetaPatch: &pb.MetaPatch{ 530 Labels: map[string]string{ 531 "c": "d", 532 }, 533 }, 534 }, 535 want: &allocationv1.GameServerAllocation{ 536 ObjectMeta: metav1.ObjectMeta{ 537 Namespace: "", 538 }, 539 Spec: allocationv1.GameServerAllocationSpec{ 540 MultiClusterSetting: allocationv1.MultiClusterSetting{ 541 Enabled: false, 542 }, 543 Scheduling: apis.Distributed, 544 Required: allocationv1.GameServerSelector{ 545 GameServerState: &ready, 546 }, 547 MetaPatch: allocationv1.MetaPatch{ 548 Labels: map[string]string{ 549 "a": "b", 550 }, 551 }, 552 }, 553 }, 554 }, 555 { 556 name: "partially empty Counters and Lists fields to GSA (PlayerAllocationFilter, CountsAndListsFilter)", 557 features: fmt.Sprintf("%s=true&%s=true", runtime.FeaturePlayerAllocationFilter, runtime.FeatureCountsAndLists), 558 in: &pb.AllocationRequest{ 559 Namespace: "", 560 MultiClusterSetting: &pb.MultiClusterSetting{}, 561 RequiredGameServerSelector: &pb.GameServerSelector{}, 562 PreferredGameServerSelectors: []*pb.GameServerSelector{}, 563 GameServerSelectors: []*pb.GameServerSelector{ 564 { 565 GameServerState: pb.GameServerSelector_READY, 566 Counters: map[string]*pb.CounterSelector{ 567 "c": { 568 MinAvailable: 10, 569 }, 570 }, 571 Lists: map[string]*pb.ListSelector{ 572 "d": { 573 ContainsValue: "abc", 574 MinAvailable: 1, 575 }, 576 }, 577 }, 578 }, 579 Lists: map[string]*pb.ListAction{ 580 "d": { 581 Capacity: wrapperspb.Int64(one), 582 }, 583 }, 584 Scheduling: pb.AllocationRequest_Distributed, 585 Metadata: &pb.MetaPatch{}, 586 }, 587 want: &allocationv1.GameServerAllocation{ 588 ObjectMeta: metav1.ObjectMeta{ 589 Namespace: "", 590 }, 591 Spec: allocationv1.GameServerAllocationSpec{ 592 MultiClusterSetting: allocationv1.MultiClusterSetting{ 593 Enabled: false, 594 }, 595 Required: allocationv1.GameServerSelector{ 596 GameServerState: &ready, 597 }, 598 Selectors: []allocationv1.GameServerSelector{ 599 { 600 GameServerState: &ready, 601 Counters: map[string]allocationv1.CounterSelector{ 602 "c": { 603 MinCount: 0, 604 MaxCount: 0, 605 MinAvailable: 10, 606 MaxAvailable: 0, 607 }, 608 }, 609 Lists: map[string]allocationv1.ListSelector{ 610 "d": { 611 ContainsValue: "abc", 612 MinAvailable: 1, 613 MaxAvailable: 0, 614 }, 615 }, 616 }, 617 }, 618 Lists: map[string]allocationv1.ListAction{ 619 "d": { 620 Capacity: &one, 621 }, 622 }, 623 Scheduling: apis.Distributed, 624 }, 625 }, 626 }, 627 } 628 for _, tc := range tests { 629 t.Run(tc.name, func(t *testing.T) { 630 t.Parallel() 631 632 runtime.FeatureTestMutex.Lock() 633 defer runtime.FeatureTestMutex.Unlock() 634 require.NoError(t, runtime.ParseFeatures(tc.features)) 635 636 out := ConvertAllocationRequestToGSA(tc.in) 637 assert.Equal(t, tc.want, out, "mismatch with want after conversion: \"%s\"", tc.name) 638 }) 639 } 640 } 641 642 func TestConvertGSAToAllocationRequest(t *testing.T) { 643 increment := agonesv1.GameServerPriorityIncrement 644 decrement := agonesv1.GameServerPriorityDecrement 645 two := int64(2) 646 twenty := int64(20) 647 648 tests := []struct { 649 name string 650 features string 651 in *allocationv1.GameServerAllocation 652 want *pb.AllocationRequest 653 }{ 654 { 655 name: "empty fields", 656 in: &allocationv1.GameServerAllocation{ 657 ObjectMeta: metav1.ObjectMeta{ 658 Namespace: "", 659 }, 660 Spec: allocationv1.GameServerAllocationSpec{ 661 MultiClusterSetting: allocationv1.MultiClusterSetting{ 662 Enabled: false, 663 }, 664 Scheduling: apis.Distributed, 665 }, 666 }, 667 want: &pb.AllocationRequest{ 668 Namespace: "", 669 MultiClusterSetting: &pb.MultiClusterSetting{}, 670 Scheduling: pb.AllocationRequest_Distributed, 671 Metadata: &pb.MetaPatch{}, 672 MetaPatch: &pb.MetaPatch{}, 673 }, 674 }, { 675 name: "empty object", 676 in: &allocationv1.GameServerAllocation{ 677 Spec: allocationv1.GameServerAllocationSpec{ 678 Scheduling: apis.Packed, 679 }, 680 }, 681 want: &pb.AllocationRequest{ 682 MultiClusterSetting: &pb.MultiClusterSetting{}, 683 Metadata: &pb.MetaPatch{}, 684 MetaPatch: &pb.MetaPatch{}, 685 }, 686 }, { 687 name: "partial GSA with CountsAndLists", 688 features: fmt.Sprintf("%s=true", runtime.FeatureCountsAndLists), 689 in: &allocationv1.GameServerAllocation{ 690 ObjectMeta: metav1.ObjectMeta{ 691 Namespace: "", 692 }, 693 Spec: allocationv1.GameServerAllocationSpec{ 694 MultiClusterSetting: allocationv1.MultiClusterSetting{ 695 Enabled: false, 696 }, 697 Selectors: []allocationv1.GameServerSelector{ 698 { 699 Counters: map[string]allocationv1.CounterSelector{ 700 "a": { 701 MinCount: 0, 702 MaxCount: 0, 703 MinAvailable: 10, 704 MaxAvailable: 0, 705 }, 706 }, 707 Lists: map[string]allocationv1.ListSelector{ 708 "b": { 709 ContainsValue: "abc", 710 MinAvailable: 1, 711 MaxAvailable: 0, 712 }, 713 }, 714 }, 715 }, 716 Priorities: []agonesv1.Priority{ 717 { 718 Type: "Counter", 719 Key: "a", 720 Order: "Ascending", 721 }, 722 { 723 Type: "List", 724 Key: "b", 725 Order: "Descending", 726 }, 727 }, 728 Counters: map[string]allocationv1.CounterAction{ 729 "a": { 730 Action: &decrement, 731 Amount: &two, 732 Capacity: &twenty, 733 }, 734 "c": { 735 Action: &increment, 736 Amount: &two, 737 }, 738 }, 739 Lists: map[string]allocationv1.ListAction{ 740 "b": { 741 AddValues: []string{"hello", "world"}, 742 }, 743 "d": { 744 Capacity: &two, 745 }, 746 "c": { 747 DeleteValues: []string{"good", "bye"}, 748 }, 749 }, 750 Scheduling: apis.Distributed, 751 }, 752 }, 753 want: &pb.AllocationRequest{ 754 Namespace: "", 755 MultiClusterSetting: &pb.MultiClusterSetting{}, 756 PreferredGameServerSelectors: []*pb.GameServerSelector{}, 757 RequiredGameServerSelector: &pb.GameServerSelector{ 758 GameServerState: pb.GameServerSelector_READY, 759 Counters: map[string]*pb.CounterSelector{ 760 "a": { 761 MinCount: 0, 762 MaxCount: 0, 763 MinAvailable: 10, 764 MaxAvailable: 0, 765 }, 766 }, 767 Lists: map[string]*pb.ListSelector{ 768 "b": { 769 ContainsValue: "abc", 770 MinAvailable: 1, 771 MaxAvailable: 0, 772 }, 773 }, 774 }, 775 GameServerSelectors: []*pb.GameServerSelector{ 776 { 777 GameServerState: pb.GameServerSelector_READY, 778 Counters: map[string]*pb.CounterSelector{ 779 "a": { 780 MinCount: 0, 781 MaxCount: 0, 782 MinAvailable: 10, 783 MaxAvailable: 0, 784 }, 785 }, 786 Lists: map[string]*pb.ListSelector{ 787 "b": { 788 ContainsValue: "abc", 789 MinAvailable: 1, 790 MaxAvailable: 0, 791 }, 792 }, 793 }, 794 }, 795 Scheduling: pb.AllocationRequest_Distributed, 796 Metadata: &pb.MetaPatch{}, 797 MetaPatch: &pb.MetaPatch{}, 798 Priorities: []*pb.Priority{ 799 { 800 Type: pb.Priority_Counter, 801 Key: "a", 802 Order: pb.Priority_Ascending, 803 }, 804 { 805 Type: pb.Priority_List, 806 Key: "b", 807 Order: pb.Priority_Descending, 808 }, 809 }, 810 Counters: map[string]*pb.CounterAction{ 811 "a": { 812 Action: wrapperspb.String(decrement), 813 Amount: wrapperspb.Int64(two), 814 Capacity: wrapperspb.Int64(twenty), 815 }, 816 "c": { 817 Action: wrapperspb.String(increment), 818 Amount: wrapperspb.Int64(two), 819 }, 820 }, 821 Lists: map[string]*pb.ListAction{ 822 "b": { 823 AddValues: []string{"hello", "world"}, 824 }, 825 "d": { 826 Capacity: wrapperspb.Int64(two), 827 }, 828 "c": { 829 DeleteValues: []string{"good", "bye"}, 830 }, 831 }, 832 }, 833 }, 834 } 835 for _, tc := range tests { 836 t.Run(tc.name, func(t *testing.T) { 837 t.Parallel() 838 839 runtime.FeatureTestMutex.Lock() 840 defer runtime.FeatureTestMutex.Unlock() 841 require.NoError(t, runtime.ParseFeatures(tc.features)) 842 843 ar := ConvertGSAToAllocationRequest(tc.in) 844 if !assert.Equal(t, tc.want, ar) { 845 t.Errorf("mismatch with want after conversion \"%s\"", tc.name) 846 } 847 }) 848 } 849 } 850 851 func TestConvertGSAToAllocationResponse(t *testing.T) { 852 tests := []struct { 853 name string 854 features string 855 in *allocationv1.GameServerAllocation 856 grpcUnallocatedStatusCode codes.Code 857 want *pb.AllocationResponse 858 wantErrCode codes.Code 859 skipConvertToGSA bool 860 }{ 861 { 862 name: "status state is set to allocated", 863 in: &allocationv1.GameServerAllocation{ 864 TypeMeta: metav1.TypeMeta{ 865 Kind: "GameServerAllocation", 866 APIVersion: "allocation.agones.dev/v1", 867 }, 868 Status: allocationv1.GameServerAllocationStatus{ 869 State: allocationv1.GameServerAllocationAllocated, 870 GameServerName: "GSN", 871 Ports: []agonesv1.GameServerStatusPort{ 872 { 873 Port: 123, 874 }, 875 { 876 Name: "port-name", 877 }, 878 }, 879 Address: "address", 880 NodeName: "node-name", 881 Source: "local", 882 }, 883 }, 884 want: &pb.AllocationResponse{ 885 GameServerName: "GSN", 886 Address: "address", 887 NodeName: "node-name", 888 Ports: []*pb.AllocationResponse_GameServerStatusPort{ 889 { 890 Port: 123, 891 }, 892 { 893 Name: "port-name", 894 }, 895 }, 896 Source: "local", 897 }, 898 }, 899 { 900 name: "status field is set to unallocated", 901 in: &allocationv1.GameServerAllocation{ 902 TypeMeta: metav1.TypeMeta{ 903 Kind: "GameServerAllocation", 904 APIVersion: "allocation.agones.dev/v1", 905 }, 906 Status: allocationv1.GameServerAllocationStatus{ 907 State: allocationv1.GameServerAllocationUnAllocated, 908 GameServerName: "GSN", 909 Ports: []agonesv1.GameServerStatusPort{ 910 { 911 Port: 123, 912 }, 913 { 914 Name: "port-name", 915 }, 916 }, 917 Address: "address", 918 NodeName: "node-name", 919 }, 920 }, 921 wantErrCode: codes.ResourceExhausted, 922 skipConvertToGSA: true, 923 }, 924 { 925 name: "status state is set to contention", 926 in: &allocationv1.GameServerAllocation{ 927 TypeMeta: metav1.TypeMeta{ 928 Kind: "GameServerAllocation", 929 APIVersion: "allocation.agones.dev/v1", 930 }, 931 Status: allocationv1.GameServerAllocationStatus{ 932 State: allocationv1.GameServerAllocationContention, 933 }, 934 }, 935 wantErrCode: codes.Aborted, 936 skipConvertToGSA: true, 937 }, 938 { 939 name: "Empty fields", 940 in: &allocationv1.GameServerAllocation{ 941 TypeMeta: metav1.TypeMeta{ 942 Kind: "GameServerAllocation", 943 APIVersion: "allocation.agones.dev/v1", 944 }, 945 Status: allocationv1.GameServerAllocationStatus{ 946 Ports: []agonesv1.GameServerStatusPort{}, 947 }, 948 }, 949 wantErrCode: codes.Unknown, 950 skipConvertToGSA: true, 951 }, 952 { 953 name: "Empty objects", 954 in: &allocationv1.GameServerAllocation{ 955 TypeMeta: metav1.TypeMeta{ 956 Kind: "GameServerAllocation", 957 APIVersion: "allocation.agones.dev/v1", 958 }, 959 Status: allocationv1.GameServerAllocationStatus{ 960 State: allocationv1.GameServerAllocationAllocated, 961 }, 962 }, 963 want: &pb.AllocationResponse{}, 964 }, 965 { 966 name: "nil objects", 967 in: nil, 968 want: nil, 969 }, 970 { 971 name: "status metadata contains labels and annotations", 972 in: &allocationv1.GameServerAllocation{ 973 TypeMeta: metav1.TypeMeta{ 974 Kind: "GameServerAllocation", 975 APIVersion: "allocation.agones.dev/v1", 976 }, 977 Status: allocationv1.GameServerAllocationStatus{ 978 State: allocationv1.GameServerAllocationAllocated, 979 GameServerName: "GSN", 980 Ports: []agonesv1.GameServerStatusPort{ 981 { 982 Port: 123, 983 }, 984 { 985 Name: "port-name", 986 }, 987 }, 988 Address: "address", 989 NodeName: "node-name", 990 Source: "local", 991 Metadata: &allocationv1.GameServerMetadata{ 992 Labels: map[string]string{ 993 "label-key": "label-value", 994 "other-key": "other-value", 995 }, 996 Annotations: map[string]string{ 997 "annotation-key": "annotation-value", 998 "other-key": "other-value", 999 }, 1000 }, 1001 }, 1002 }, 1003 want: &pb.AllocationResponse{ 1004 GameServerName: "GSN", 1005 Address: "address", 1006 NodeName: "node-name", 1007 Ports: []*pb.AllocationResponse_GameServerStatusPort{ 1008 { 1009 Port: 123, 1010 }, 1011 { 1012 Name: "port-name", 1013 }, 1014 }, 1015 Source: "local", 1016 Metadata: &pb.AllocationResponse_GameServerMetadata{ 1017 Labels: map[string]string{ 1018 "label-key": "label-value", 1019 "other-key": "other-value", 1020 }, 1021 Annotations: map[string]string{ 1022 "annotation-key": "annotation-value", 1023 "other-key": "other-value", 1024 }, 1025 }, 1026 }, 1027 }, 1028 { 1029 name: "addresses convert", 1030 in: &allocationv1.GameServerAllocation{ 1031 TypeMeta: metav1.TypeMeta{ 1032 Kind: "GameServerAllocation", 1033 APIVersion: "allocation.agones.dev/v1", 1034 }, 1035 Status: allocationv1.GameServerAllocationStatus{ 1036 State: allocationv1.GameServerAllocationAllocated, 1037 GameServerName: "GSN", 1038 Ports: []agonesv1.GameServerStatusPort{ 1039 { 1040 Port: 123, 1041 }, 1042 { 1043 Name: "port-name", 1044 }, 1045 }, 1046 Address: "address", 1047 Addresses: []corev1.NodeAddress{ 1048 {Type: "SomeAddressType", Address: "123.123.123.123"}, 1049 {Type: "AnotherAddressType", Address: "321.321.321.321"}, 1050 }, 1051 NodeName: "node-name", 1052 Source: "local", 1053 Metadata: &allocationv1.GameServerMetadata{ 1054 Labels: map[string]string{ 1055 "label-key": "label-value", 1056 "other-key": "other-value", 1057 }, 1058 Annotations: map[string]string{ 1059 "annotation-key": "annotation-value", 1060 "other-key": "other-value", 1061 }, 1062 }, 1063 }, 1064 }, 1065 want: &pb.AllocationResponse{ 1066 GameServerName: "GSN", 1067 Address: "address", 1068 Addresses: []*pb.AllocationResponse_GameServerStatusAddress{ 1069 {Type: "SomeAddressType", Address: "123.123.123.123"}, 1070 {Type: "AnotherAddressType", Address: "321.321.321.321"}, 1071 }, 1072 NodeName: "node-name", 1073 Ports: []*pb.AllocationResponse_GameServerStatusPort{ 1074 { 1075 Port: 123, 1076 }, 1077 { 1078 Name: "port-name", 1079 }, 1080 }, 1081 Source: "local", 1082 Metadata: &pb.AllocationResponse_GameServerMetadata{ 1083 Labels: map[string]string{ 1084 "label-key": "label-value", 1085 "other-key": "other-value", 1086 }, 1087 Annotations: map[string]string{ 1088 "annotation-key": "annotation-value", 1089 "other-key": "other-value", 1090 }, 1091 }, 1092 }, 1093 }, 1094 { 1095 name: "all fields are set (CountsAndLists)", 1096 features: fmt.Sprintf("%s=true", runtime.FeatureCountsAndLists), 1097 in: &allocationv1.GameServerAllocation{ 1098 TypeMeta: metav1.TypeMeta{ 1099 Kind: "GameServerAllocation", 1100 APIVersion: "allocation.agones.dev/v1", 1101 }, 1102 Status: allocationv1.GameServerAllocationStatus{ 1103 State: allocationv1.GameServerAllocationAllocated, 1104 GameServerName: "GSN", 1105 Ports: []agonesv1.GameServerStatusPort{ 1106 { 1107 Port: 123, 1108 }, 1109 { 1110 Name: "port-name", 1111 }, 1112 }, 1113 Address: "address", 1114 Addresses: []corev1.NodeAddress{ 1115 {Type: "SomeAddressType", Address: "123.123.123.123"}, 1116 {Type: "AnotherAddressType", Address: "321.321.321.321"}, 1117 }, 1118 NodeName: "node-name", 1119 Source: "local", 1120 Metadata: &allocationv1.GameServerMetadata{ 1121 Labels: map[string]string{ 1122 "label-key": "label-value", 1123 "other-key": "other-value", 1124 }, 1125 Annotations: map[string]string{ 1126 "annotation-key": "annotation-value", 1127 "other-key": "other-value", 1128 }, 1129 }, 1130 Counters: map[string]agonesv1.CounterStatus{ 1131 "p": { 1132 Count: 0, 1133 Capacity: 1, 1134 }, 1135 }, 1136 Lists: map[string]agonesv1.ListStatus{ 1137 "p": { 1138 Values: []string{"foo", "bar", "baz"}, 1139 Capacity: 10, 1140 }, 1141 }, 1142 }, 1143 }, 1144 want: &pb.AllocationResponse{ 1145 GameServerName: "GSN", 1146 Address: "address", 1147 Addresses: []*pb.AllocationResponse_GameServerStatusAddress{ 1148 {Type: "SomeAddressType", Address: "123.123.123.123"}, 1149 {Type: "AnotherAddressType", Address: "321.321.321.321"}, 1150 }, 1151 NodeName: "node-name", 1152 Ports: []*pb.AllocationResponse_GameServerStatusPort{ 1153 { 1154 Port: 123, 1155 }, 1156 { 1157 Name: "port-name", 1158 }, 1159 }, 1160 Source: "local", 1161 Metadata: &pb.AllocationResponse_GameServerMetadata{ 1162 Labels: map[string]string{ 1163 "label-key": "label-value", 1164 "other-key": "other-value", 1165 }, 1166 Annotations: map[string]string{ 1167 "annotation-key": "annotation-value", 1168 "other-key": "other-value", 1169 }, 1170 }, 1171 Counters: map[string]*pb.AllocationResponse_CounterStatus{ 1172 "p": { 1173 Count: wrapperspb.Int64(0), 1174 Capacity: wrapperspb.Int64(1), 1175 }, 1176 }, 1177 Lists: map[string]*pb.AllocationResponse_ListStatus{ 1178 "p": { 1179 Values: []string{"foo", "bar", "baz"}, 1180 Capacity: wrapperspb.Int64(10), 1181 }, 1182 }, 1183 }, 1184 }, 1185 { 1186 name: "Counters fields are set (CountsAndLists)", 1187 features: fmt.Sprintf("%s=true", runtime.FeatureCountsAndLists), 1188 in: &allocationv1.GameServerAllocation{ 1189 TypeMeta: metav1.TypeMeta{ 1190 Kind: "GameServerAllocation", 1191 APIVersion: "allocation.agones.dev/v1", 1192 }, 1193 Status: allocationv1.GameServerAllocationStatus{ 1194 State: allocationv1.GameServerAllocationAllocated, 1195 GameServerName: "GSN", 1196 Ports: []agonesv1.GameServerStatusPort{ 1197 { 1198 Port: 123, 1199 }, 1200 { 1201 Name: "port-name", 1202 }, 1203 }, 1204 Address: "address", 1205 Addresses: []corev1.NodeAddress{ 1206 {Type: "SomeAddressType", Address: "123.123.123.123"}, 1207 {Type: "AnotherAddressType", Address: "321.321.321.321"}, 1208 }, 1209 NodeName: "node-name", 1210 Source: "local", 1211 Metadata: &allocationv1.GameServerMetadata{ 1212 Labels: map[string]string{ 1213 "label-key": "label-value", 1214 "other-key": "other-value", 1215 }, 1216 Annotations: map[string]string{ 1217 "annotation-key": "annotation-value", 1218 "other-key": "other-value", 1219 }, 1220 }, 1221 Counters: map[string]agonesv1.CounterStatus{ 1222 "p": { 1223 Count: 0, 1224 Capacity: 1, 1225 }, 1226 }, 1227 }, 1228 }, 1229 want: &pb.AllocationResponse{ 1230 GameServerName: "GSN", 1231 Address: "address", 1232 Addresses: []*pb.AllocationResponse_GameServerStatusAddress{ 1233 {Type: "SomeAddressType", Address: "123.123.123.123"}, 1234 {Type: "AnotherAddressType", Address: "321.321.321.321"}, 1235 }, 1236 NodeName: "node-name", 1237 Ports: []*pb.AllocationResponse_GameServerStatusPort{ 1238 { 1239 Port: 123, 1240 }, 1241 { 1242 Name: "port-name", 1243 }, 1244 }, 1245 Source: "local", 1246 Metadata: &pb.AllocationResponse_GameServerMetadata{ 1247 Labels: map[string]string{ 1248 "label-key": "label-value", 1249 "other-key": "other-value", 1250 }, 1251 Annotations: map[string]string{ 1252 "annotation-key": "annotation-value", 1253 "other-key": "other-value", 1254 }, 1255 }, 1256 Counters: map[string]*pb.AllocationResponse_CounterStatus{ 1257 "p": { 1258 Count: wrapperspb.Int64(0), 1259 Capacity: wrapperspb.Int64(1), 1260 }, 1261 }, 1262 }, 1263 }, 1264 { 1265 name: "Lists fields are set (CountsAndLists)", 1266 features: fmt.Sprintf("%s=true", runtime.FeatureCountsAndLists), 1267 in: &allocationv1.GameServerAllocation{ 1268 TypeMeta: metav1.TypeMeta{ 1269 Kind: "GameServerAllocation", 1270 APIVersion: "allocation.agones.dev/v1", 1271 }, 1272 Status: allocationv1.GameServerAllocationStatus{ 1273 State: allocationv1.GameServerAllocationAllocated, 1274 GameServerName: "GSN", 1275 Ports: []agonesv1.GameServerStatusPort{ 1276 { 1277 Port: 123, 1278 }, 1279 { 1280 Name: "port-name", 1281 }, 1282 }, 1283 Address: "address", 1284 Addresses: []corev1.NodeAddress{ 1285 {Type: "SomeAddressType", Address: "123.123.123.123"}, 1286 {Type: "AnotherAddressType", Address: "321.321.321.321"}, 1287 }, 1288 NodeName: "node-name", 1289 Source: "local", 1290 Metadata: &allocationv1.GameServerMetadata{ 1291 Labels: map[string]string{ 1292 "label-key": "label-value", 1293 "other-key": "other-value", 1294 }, 1295 Annotations: map[string]string{ 1296 "annotation-key": "annotation-value", 1297 "other-key": "other-value", 1298 }, 1299 }, 1300 Lists: map[string]agonesv1.ListStatus{ 1301 "p": { 1302 Values: []string{"foo", "bar", "baz"}, 1303 Capacity: 10, 1304 }, 1305 }, 1306 }, 1307 }, 1308 want: &pb.AllocationResponse{ 1309 GameServerName: "GSN", 1310 Address: "address", 1311 Addresses: []*pb.AllocationResponse_GameServerStatusAddress{ 1312 {Type: "SomeAddressType", Address: "123.123.123.123"}, 1313 {Type: "AnotherAddressType", Address: "321.321.321.321"}, 1314 }, 1315 NodeName: "node-name", 1316 Ports: []*pb.AllocationResponse_GameServerStatusPort{ 1317 { 1318 Port: 123, 1319 }, 1320 { 1321 Name: "port-name", 1322 }, 1323 }, 1324 Source: "local", 1325 Metadata: &pb.AllocationResponse_GameServerMetadata{ 1326 Labels: map[string]string{ 1327 "label-key": "label-value", 1328 "other-key": "other-value", 1329 }, 1330 Annotations: map[string]string{ 1331 "annotation-key": "annotation-value", 1332 "other-key": "other-value", 1333 }, 1334 }, 1335 Lists: map[string]*pb.AllocationResponse_ListStatus{ 1336 "p": { 1337 Values: []string{"foo", "bar", "baz"}, 1338 Capacity: wrapperspb.Int64(10), 1339 }, 1340 }, 1341 }, 1342 }, 1343 { 1344 name: "status field is set to unallocated, non-default unallocated", 1345 in: &allocationv1.GameServerAllocation{ 1346 TypeMeta: metav1.TypeMeta{ 1347 Kind: "GameServerAllocation", 1348 APIVersion: "allocation.agones.dev/v1", 1349 }, 1350 Status: allocationv1.GameServerAllocationStatus{ 1351 State: allocationv1.GameServerAllocationUnAllocated, 1352 GameServerName: "GSN", 1353 Ports: []agonesv1.GameServerStatusPort{ 1354 { 1355 Port: 123, 1356 }, 1357 { 1358 Name: "port-name", 1359 }, 1360 }, 1361 Address: "address", 1362 NodeName: "node-name", 1363 }, 1364 }, 1365 grpcUnallocatedStatusCode: codes.Unimplemented, 1366 wantErrCode: codes.Unimplemented, 1367 skipConvertToGSA: true, 1368 }, 1369 } 1370 for _, tc := range tests { 1371 t.Run(tc.name, func(t *testing.T) { 1372 t.Parallel() 1373 runtime.FeatureTestMutex.Lock() 1374 defer runtime.FeatureTestMutex.Unlock() 1375 require.NoError(t, runtime.ParseFeatures(tc.features)) 1376 1377 grpcUnallocatedStatusCode := tc.grpcUnallocatedStatusCode 1378 if grpcUnallocatedStatusCode == codes.OK { 1379 grpcUnallocatedStatusCode = codes.ResourceExhausted 1380 } 1381 1382 out, err := ConvertGSAToAllocationResponse(tc.in, grpcUnallocatedStatusCode) 1383 if tc.wantErrCode != 0 { 1384 st, ok := status.FromError(err) 1385 if !assert.True(t, ok) { 1386 return 1387 } 1388 assert.Equal(t, tc.wantErrCode, st.Code()) 1389 } 1390 if !assert.Equal(t, tc.want, out) { 1391 t.Errorf("mismatch with want after conversion: \"%s\"", tc.name) 1392 } 1393 1394 if !tc.skipConvertToGSA { 1395 source := "" 1396 if tc.in != nil { 1397 source = tc.in.Status.Source 1398 } 1399 gsa := ConvertAllocationResponseToGSA(tc.want, source) 1400 if !assert.Equal(t, tc.in, gsa) { 1401 t.Errorf("mismatch with input after double conversion \"%s\"", tc.name) 1402 } 1403 } 1404 }) 1405 } 1406 } 1407 1408 func TestConvertAllocationResponseToGSA(t *testing.T) { 1409 tests := []struct { 1410 name string 1411 features string 1412 in *pb.AllocationResponse 1413 want *allocationv1.GameServerAllocation 1414 }{ 1415 { 1416 name: "Empty fields", 1417 in: &pb.AllocationResponse{ 1418 Ports: []*pb.AllocationResponse_GameServerStatusPort{}, 1419 Source: "33.188.237.156:443", 1420 }, 1421 want: &allocationv1.GameServerAllocation{ 1422 TypeMeta: metav1.TypeMeta{ 1423 Kind: "GameServerAllocation", 1424 APIVersion: "allocation.agones.dev/v1", 1425 }, 1426 Status: allocationv1.GameServerAllocationStatus{ 1427 State: allocationv1.GameServerAllocationAllocated, 1428 Source: "33.188.237.156:443", 1429 }, 1430 }, 1431 }, 1432 { 1433 name: "Addresses convert", 1434 in: &pb.AllocationResponse{ 1435 Ports: []*pb.AllocationResponse_GameServerStatusPort{}, 1436 Source: "33.188.237.156:443", 1437 Addresses: []*pb.AllocationResponse_GameServerStatusAddress{ 1438 {Type: "SomeAddressType", Address: "123.123.123.123"}, 1439 {Type: "AnotherAddressType", Address: "321.321.321.321"}, 1440 }, 1441 }, 1442 want: &allocationv1.GameServerAllocation{ 1443 TypeMeta: metav1.TypeMeta{ 1444 Kind: "GameServerAllocation", 1445 APIVersion: "allocation.agones.dev/v1", 1446 }, 1447 Status: allocationv1.GameServerAllocationStatus{ 1448 State: allocationv1.GameServerAllocationAllocated, 1449 Source: "33.188.237.156:443", 1450 Addresses: []corev1.NodeAddress{ 1451 {Type: "SomeAddressType", Address: "123.123.123.123"}, 1452 {Type: "AnotherAddressType", Address: "321.321.321.321"}, 1453 }, 1454 }, 1455 }, 1456 }, 1457 { 1458 name: "Counters and Lists convert", 1459 features: fmt.Sprintf("%s=true", runtime.FeatureCountsAndLists), 1460 in: &pb.AllocationResponse{ 1461 Ports: []*pb.AllocationResponse_GameServerStatusPort{}, 1462 Source: "33.188.237.156:443", 1463 Counters: map[string]*pb.AllocationResponse_CounterStatus{ 1464 "p": { 1465 Count: wrapperspb.Int64(1), 1466 Capacity: wrapperspb.Int64(3), 1467 }, 1468 }, 1469 Lists: map[string]*pb.AllocationResponse_ListStatus{ 1470 "p": { 1471 Values: []string{"foo", "bar", "baz"}, 1472 Capacity: wrapperspb.Int64(3), 1473 }, 1474 }, 1475 }, 1476 want: &allocationv1.GameServerAllocation{ 1477 TypeMeta: metav1.TypeMeta{ 1478 Kind: "GameServerAllocation", 1479 APIVersion: "allocation.agones.dev/v1", 1480 }, 1481 Status: allocationv1.GameServerAllocationStatus{ 1482 State: allocationv1.GameServerAllocationAllocated, 1483 Source: "33.188.237.156:443", 1484 Counters: map[string]agonesv1.CounterStatus{ 1485 "p": { 1486 Count: 1, 1487 Capacity: 3, 1488 }, 1489 }, 1490 Lists: map[string]agonesv1.ListStatus{ 1491 "p": { 1492 Values: []string{"foo", "bar", "baz"}, 1493 Capacity: 3, 1494 }, 1495 }, 1496 }, 1497 }, 1498 }, 1499 { 1500 name: "Counters convert", 1501 features: fmt.Sprintf("%s=true", runtime.FeatureCountsAndLists), 1502 in: &pb.AllocationResponse{ 1503 Ports: []*pb.AllocationResponse_GameServerStatusPort{}, 1504 Source: "33.188.237.156:443", 1505 Counters: map[string]*pb.AllocationResponse_CounterStatus{ 1506 "p": { 1507 Count: wrapperspb.Int64(1), 1508 Capacity: wrapperspb.Int64(3), 1509 }, 1510 }, 1511 }, 1512 want: &allocationv1.GameServerAllocation{ 1513 TypeMeta: metav1.TypeMeta{ 1514 Kind: "GameServerAllocation", 1515 APIVersion: "allocation.agones.dev/v1", 1516 }, 1517 Status: allocationv1.GameServerAllocationStatus{ 1518 State: allocationv1.GameServerAllocationAllocated, 1519 Source: "33.188.237.156:443", 1520 Counters: map[string]agonesv1.CounterStatus{ 1521 "p": { 1522 Count: 1, 1523 Capacity: 3, 1524 }, 1525 }, 1526 }, 1527 }, 1528 }, 1529 { 1530 name: "List convert", 1531 features: fmt.Sprintf("%s=true", runtime.FeatureCountsAndLists), 1532 in: &pb.AllocationResponse{ 1533 Ports: []*pb.AllocationResponse_GameServerStatusPort{}, 1534 Source: "33.188.237.156:443", 1535 Lists: map[string]*pb.AllocationResponse_ListStatus{ 1536 "p": { 1537 Values: []string{"foo", "bar", "baz"}, 1538 Capacity: wrapperspb.Int64(3), 1539 }, 1540 }, 1541 }, 1542 want: &allocationv1.GameServerAllocation{ 1543 TypeMeta: metav1.TypeMeta{ 1544 Kind: "GameServerAllocation", 1545 APIVersion: "allocation.agones.dev/v1", 1546 }, 1547 Status: allocationv1.GameServerAllocationStatus{ 1548 State: allocationv1.GameServerAllocationAllocated, 1549 Source: "33.188.237.156:443", 1550 Lists: map[string]agonesv1.ListStatus{ 1551 "p": { 1552 Values: []string{"foo", "bar", "baz"}, 1553 Capacity: 3, 1554 }, 1555 }, 1556 }, 1557 }, 1558 }, 1559 } 1560 for _, tc := range tests { 1561 t.Run(tc.name, func(t *testing.T) { 1562 t.Parallel() 1563 runtime.FeatureTestMutex.Lock() 1564 defer runtime.FeatureTestMutex.Unlock() 1565 require.NoError(t, runtime.ParseFeatures(tc.features)) 1566 out := ConvertAllocationResponseToGSA(tc.in, tc.in.Source) 1567 if !assert.Equal(t, tc.want, out) { 1568 t.Errorf("mismatch with want after conversion: \"%s\"", tc.name) 1569 } 1570 }) 1571 } 1572 }