@@ -1682,10 +1682,37 @@ var _ = common.SIGDescribe("Services", func() {
1682
1682
1683
1683
service := t .BuildServiceSpec ()
1684
1684
service .Spec .Type = v1 .ServiceTypeNodePort
1685
-
1685
+ numberOfRetries := 5
1686
1686
ginkgo .By ("creating service " + serviceName + " with type NodePort in namespace " + ns )
1687
- service , err := t .CreateService (service )
1688
- framework .ExpectNoError (err , "failed to create service: %s in namespace: %s" , serviceName , ns )
1687
+ var err error
1688
+ for i := 0 ; i < numberOfRetries ; i ++ {
1689
+ port , err := e2eservice .GetUnusedStaticNodePort ()
1690
+ framework .ExpectNoError (err , "Static node port allocator was not able to find a free nodeport." )
1691
+ service .Spec .Ports [0 ].NodePort = port
1692
+ service , err = t .CreateService (service )
1693
+ // We will later delete this service and then recreate it with same nodeport. We need to ensure that
1694
+ // another e2e test doesn't start listening on our old nodeport and conflicts re-creation of service
1695
+ // hence we use ReserveStaticNodePort.
1696
+ if err == nil {
1697
+ nodePort := service .Spec .Ports [0 ].NodePort
1698
+ ok := e2eservice .ReserveStaticNodePort (nodePort )
1699
+ if ! ok {
1700
+ // We could not reserve the allocated port which means the port was either invalid or was reserved by another test.
1701
+ // This indicates a problem in code and we have a log message to debug it.
1702
+ framework .Failf ("Static node port allocator was not able to reserve nodeport: %d" , nodePort )
1703
+ }
1704
+ break
1705
+ }
1706
+ if apierrors .IsConflict (err ) {
1707
+ framework .Logf ("node port %d is already allocated to other service, retrying ... : %v" , port , err )
1708
+ continue
1709
+ }
1710
+ framework .ExpectNoError (err , "failed to create service: %s in namespace: %s" , serviceName , ns )
1711
+
1712
+ }
1713
+
1714
+ nodePort := service .Spec .Ports [0 ].NodePort
1715
+ defer e2eservice .ReleaseStaticNodePort (nodePort )
1689
1716
1690
1717
if service .Spec .Type != v1 .ServiceTypeNodePort {
1691
1718
framework .Failf ("got unexpected Spec.Type for new service: %v" , service )
@@ -1700,7 +1727,6 @@ var _ = common.SIGDescribe("Services", func() {
1700
1727
if ! e2eservice .NodePortRange .Contains (int (port .NodePort )) {
1701
1728
framework .Failf ("got unexpected (out-of-range) port for new service: %v" , service )
1702
1729
}
1703
- nodePort := port .NodePort
1704
1730
1705
1731
ginkgo .By ("deleting original service " + serviceName )
1706
1732
err = t .DeleteService (serviceName )
@@ -3931,10 +3957,37 @@ var _ = common.SIGDescribe("Services", func() {
3931
3957
}
3932
3958
3933
3959
ginkgo .By ("creating the service" )
3934
- svc , err := jig .CreateLoadBalancerServiceWaitForClusterIPOnly (func (svc * v1.Service ) {
3935
- svc .Spec .ExternalTrafficPolicy = v1 .ServiceExternalTrafficPolicyLocal
3936
- })
3937
- framework .ExpectNoError (err , "creating the service" )
3960
+ var svc * v1.Service
3961
+ numberOfRetries := 5
3962
+ for i := 0 ; i < numberOfRetries ; i ++ {
3963
+ port , err := e2eservice .GetUnusedStaticNodePort ()
3964
+ framework .ExpectNoError (err , "Static node port allocator was not able to find a free nodeport." )
3965
+ svc , err = jig .CreateLoadBalancerServiceWaitForClusterIPOnly (func (svc * v1.Service ) {
3966
+ svc .Spec .ExternalTrafficPolicy = v1 .ServiceExternalTrafficPolicyLocal
3967
+ svc .Spec .HealthCheckNodePort = port
3968
+ })
3969
+ // We will later convert this service to Cluster traffic policy, but we need to ensure that
3970
+ // another e2e test doesn't start listening on our old HealthCheckNodePort when we
3971
+ // do that, so we use ReserveStaticNodePort.
3972
+ if err == nil {
3973
+ staticHealthCheckPort := svc .Spec .HealthCheckNodePort
3974
+ ok := e2eservice .ReserveStaticNodePort (staticHealthCheckPort )
3975
+ if ! ok {
3976
+ // We could not reserve the allocated port which means the port was either invalid or was reserved by another test.
3977
+ // This indicates a problem in code and we have a log message to debug it.
3978
+ framework .Failf ("Static node port allocator was not able to reserve healthcheck nodeport: %d" , staticHealthCheckPort )
3979
+ }
3980
+ break
3981
+ }
3982
+ if apierrors .IsConflict (err ) {
3983
+ framework .Logf ("node port %d is already allocated to other service, retrying ... : %v" , port , err )
3984
+ continue
3985
+ }
3986
+ framework .ExpectNoError (err , "failed to create service: %s in namespace: %s" , serviceName , namespace )
3987
+
3988
+ }
3989
+
3990
+ defer e2eservice .ReleaseStaticNodePort (svc .Spec .HealthCheckNodePort )
3938
3991
nodePortStr := fmt .Sprintf ("%d" , svc .Spec .Ports [0 ].NodePort )
3939
3992
hcNodePortStr := fmt .Sprintf ("%d" , svc .Spec .HealthCheckNodePort )
3940
3993
framework .Logf ("NodePort is %s, HealthCheckNodePort is %s" , nodePortStr , hcNodePortStr )
@@ -4043,7 +4096,6 @@ var _ = common.SIGDescribe("Services", func() {
4043
4096
}
4044
4097
deadline = time .Now ().Add (e2eservice .KubeProxyEndpointLagTimeout )
4045
4098
4046
- // FIXME: this is racy; we need to use a reserved HCNP here.
4047
4099
ginkgo .By ("ensuring that the HealthCheckNodePort no longer responds on the endpoint node when ExternalTrafficPolicy is Cluster" )
4048
4100
checkOneHealthCheck (endpointNodeIP , false , "" , deadline )
4049
4101
ginkgo .By ("ensuring that the HealthCheckNodePort no longer responds on the execpod node when ExternalTrafficPolicy is Cluster" )
@@ -4062,7 +4114,6 @@ var _ = common.SIGDescribe("Services", func() {
4062
4114
_ , err = jig .UpdateService (ctx , func (svc * v1.Service ) {
4063
4115
svc .Spec .ExternalTrafficPolicy = v1 .ServiceExternalTrafficPolicyLocal
4064
4116
// Request the same healthCheckNodePort as before, to test the user-requested allocation path
4065
- // FIXME: we need to use a reserved HCNP here.
4066
4117
svc .Spec .HealthCheckNodePort = oldHealthCheckNodePort
4067
4118
})
4068
4119
framework .ExpectNoError (err , "updating ExternalTrafficPolicy and HealthCheckNodePort" )
0 commit comments