@@ -19,14 +19,15 @@ package service
19
19
import (
20
20
"context"
21
21
"encoding/json"
22
- "reflect"
23
22
"testing"
24
23
"time"
25
24
26
25
corev1 "k8s.io/api/core/v1"
26
+ apiequality "k8s.io/apimachinery/pkg/api/equality"
27
27
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28
28
"k8s.io/apimachinery/pkg/types"
29
29
"k8s.io/apimachinery/pkg/util/strategicpatch"
30
+ "k8s.io/apimachinery/pkg/util/wait"
30
31
utilfeature "k8s.io/apiserver/pkg/util/feature"
31
32
"k8s.io/client-go/informers"
32
33
clientset "k8s.io/client-go/kubernetes"
@@ -39,6 +40,7 @@ import (
39
40
"k8s.io/kubernetes/test/integration/framework"
40
41
"k8s.io/utils/net"
41
42
utilpointer "k8s.io/utils/pointer"
43
+ "k8s.io/utils/ptr"
42
44
)
43
45
44
46
// Test_ServiceLoadBalancerAllocateNodePorts tests that a Service with spec.allocateLoadBalancerNodePorts=false
@@ -644,21 +646,62 @@ func newServiceController(t *testing.T, client *clientset.Clientset) (*serviceco
644
646
645
647
// Test_ServiceLoadBalancerIPMode tests whether the cloud provider has correctly updated the ipMode field.
646
648
func Test_ServiceLoadBalancerIPMode (t * testing.T ) {
647
- ipModeVIP := corev1 .LoadBalancerIPModeVIP
649
+ baseService := & corev1.Service {
650
+ ObjectMeta : metav1.ObjectMeta {
651
+ Name : "test-update-load-balancer-ip-mode" ,
652
+ },
653
+ Spec : corev1.ServiceSpec {
654
+ Type : corev1 .ServiceTypeLoadBalancer ,
655
+ Ports : []corev1.ServicePort {{
656
+ Port : int32 (80 ),
657
+ }},
658
+ },
659
+ }
660
+
648
661
testCases := []struct {
649
- ipModeEnabled bool
650
- externalIP string
651
- expectedIPMode * corev1.LoadBalancerIPMode
662
+ ipModeEnabled bool
663
+ setIPMode * corev1.LoadBalancerIPMode
664
+ externalIP string
665
+ expectedIngress corev1.LoadBalancerIngress
652
666
}{
653
667
{
654
- ipModeEnabled : false ,
655
- externalIP : "1.2.3.4" ,
656
- expectedIPMode : nil ,
668
+ ipModeEnabled : false ,
669
+ externalIP : "1.2.3.4" ,
670
+ expectedIngress : corev1.LoadBalancerIngress {
671
+ IP : "1.2.3.4" ,
672
+ IPMode : nil ,
673
+ Ports : []corev1.PortStatus {{Port : 80 , Protocol : corev1 .ProtocolTCP }},
674
+ },
657
675
},
658
676
{
659
- ipModeEnabled : true ,
660
- externalIP : "1.2.3.5" ,
661
- expectedIPMode : & ipModeVIP ,
677
+ ipModeEnabled : true ,
678
+ setIPMode : nil ,
679
+ externalIP : "1.2.3.4" ,
680
+ expectedIngress : corev1.LoadBalancerIngress {
681
+ IP : "1.2.3.4" ,
682
+ IPMode : ptr .To (corev1 .LoadBalancerIPModeVIP ),
683
+ Ports : []corev1.PortStatus {{Port : 80 , Protocol : corev1 .ProtocolTCP }},
684
+ },
685
+ },
686
+ {
687
+ ipModeEnabled : true ,
688
+ setIPMode : ptr .To (corev1 .LoadBalancerIPModeVIP ),
689
+ externalIP : "1.2.3.4" ,
690
+ expectedIngress : corev1.LoadBalancerIngress {
691
+ IP : "1.2.3.4" ,
692
+ IPMode : ptr .To (corev1 .LoadBalancerIPModeVIP ),
693
+ Ports : []corev1.PortStatus {{Port : 80 , Protocol : corev1 .ProtocolTCP }},
694
+ },
695
+ },
696
+ {
697
+ ipModeEnabled : true ,
698
+ setIPMode : ptr .To (corev1 .LoadBalancerIPModeProxy ),
699
+ externalIP : "1.2.3.4" ,
700
+ expectedIngress : corev1.LoadBalancerIngress {
701
+ IP : "1.2.3.4" ,
702
+ IPMode : ptr .To (corev1 .LoadBalancerIPModeProxy ),
703
+ Ports : []corev1.PortStatus {{Port : 80 , Protocol : corev1 .ProtocolTCP }},
704
+ },
662
705
},
663
706
}
664
707
@@ -678,43 +721,68 @@ func Test_ServiceLoadBalancerIPMode(t *testing.T) {
678
721
679
722
controller , cloud , informer := newServiceController (t , client )
680
723
cloud .ExternalIP = net .ParseIPSloppy (tc .externalIP )
724
+ cloud .BalancerIPMode = tc .expectedIngress .IPMode
681
725
682
726
ctx , cancel := context .WithCancel (context .Background ())
683
727
defer cancel ()
684
728
informer .Start (ctx .Done ())
685
729
go controller .Run (ctx , 1 , controllersmetrics .NewControllerManagerMetrics ("loadbalancer-test" ))
686
730
687
- service := & corev1.Service {
688
- ObjectMeta : metav1.ObjectMeta {
689
- Name : "test-update-load-balancer-ip-mode" ,
690
- },
691
- Spec : corev1.ServiceSpec {
692
- Type : corev1 .ServiceTypeLoadBalancer ,
693
- Ports : []corev1.ServicePort {{
694
- Port : int32 (80 ),
695
- }},
696
- },
697
- }
698
-
699
- service , err = client .CoreV1 ().Services (ns .Name ).Create (ctx , service , metav1.CreateOptions {})
731
+ service , err := client .CoreV1 ().Services (ns .Name ).Create (ctx , baseService , metav1.CreateOptions {})
700
732
if err != nil {
701
733
t .Fatalf ("Error creating test service: %v" , err )
702
734
}
703
735
704
- time .Sleep (5 * time .Second ) // sleep 5 second to wait for the service controller reconcile
705
- service , err = client .CoreV1 ().Services (ns .Name ).Get (ctx , service .Name , metav1.GetOptions {})
736
+ err = wait .PollUntilContextTimeout (ctx , 500 * time .Millisecond , 10 * time .Second , true , func (_ context.Context ) (done bool , err error ) {
737
+ service , err = client .CoreV1 ().Services (ns .Name ).Get (ctx , service .Name , metav1.GetOptions {})
738
+ if err != nil {
739
+ t .Fatalf ("Error getting test service: %v" , err )
740
+ }
741
+ if len (service .Status .LoadBalancer .Ingress ) != 1 {
742
+ return false , nil
743
+ }
744
+ return true , nil
745
+ })
706
746
if err != nil {
707
- t .Fatalf ("Error getting test service: %v" , err )
747
+ t .Fatalf ("unexpected load balancer status" )
708
748
}
709
749
710
- if len (service .Status .LoadBalancer .Ingress ) == 0 {
711
- t .Fatalf ("unexpected load balancer status" )
750
+ ingress := service .Status .LoadBalancer .Ingress [0 ]
751
+ if ! apiequality .Semantic .DeepEqual (& ingress , & tc .expectedIngress ) {
752
+ t .Errorf ("expected Ingress %v, got IP %v" ,
753
+ ingress , tc .expectedIngress )
754
+ if ingress .IPMode != nil && tc .expectedIngress .IPMode != nil {
755
+ t .Logf ("IPMode %v expected %v" , * ingress .IPMode , * tc .expectedIngress .IPMode )
756
+ }
712
757
}
713
758
714
- gotIngress := service .Status .LoadBalancer .Ingress [0 ]
715
- if gotIngress .IP != tc .externalIP || ! reflect .DeepEqual (gotIngress .IPMode , tc .expectedIPMode ) {
716
- t .Errorf ("unexpected load balancer ingress, got ingress %v, expected IP %v, expected ipMode %v" ,
717
- gotIngress , tc .externalIP , tc .expectedIPMode )
759
+ // mutate the service and check the status is preserved
760
+ newService := service .DeepCopy ()
761
+ newService .Spec .Ports [0 ].Port = 443
762
+ service , err = client .CoreV1 ().Services (ns .Name ).Update (ctx , newService , metav1.UpdateOptions {})
763
+ if err != nil {
764
+ t .Fatalf ("Error updating test service: %v" , err )
765
+ }
766
+
767
+ expectedIngress := tc .expectedIngress
768
+ expectedIngress .Ports [0 ].Port = 443
769
+ err = wait .PollUntilContextTimeout (ctx , 500 * time .Millisecond , 10 * time .Second , true , func (_ context.Context ) (done bool , err error ) {
770
+ service , err = client .CoreV1 ().Services (ns .Name ).Get (ctx , service .Name , metav1.GetOptions {})
771
+ if err != nil {
772
+ t .Fatalf ("Error getting test service: %v" , err )
773
+ }
774
+ if len (service .Status .LoadBalancer .Ingress ) != 1 {
775
+ return false , nil
776
+ }
777
+ ingress = service .Status .LoadBalancer .Ingress [0 ]
778
+ if ! apiequality .Semantic .DeepEqual (& ingress , & expectedIngress ) {
779
+ t .Logf ("Ingress %v Expected %v" , ingress , expectedIngress )
780
+ return false , nil
781
+ }
782
+ return true , nil
783
+ })
784
+ if err != nil {
785
+ t .Fatalf ("unexpected load balancer status" )
718
786
}
719
787
})
720
788
}
0 commit comments