mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
Svc REST: Better NodePort tests
This commit ports the NodePort test from rest_test to storage_test. It's not a direct port, though. I have added many more cases (much more exhaustive) and more assertions. This includes cases for gate MixedProtocolLBService.
This commit is contained in:
parent
46d7289655
commit
2212924a96
@ -25,7 +25,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
|
||||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@ -288,79 +287,6 @@ func makeIPNet6(t *testing.T) *net.IPNet {
|
|||||||
return net
|
return net
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceRegistryCreateMultiNodePortsService(t *testing.T) {
|
|
||||||
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
|
|
||||||
defer server.Terminate(t)
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
svc *api.Service
|
|
||||||
name string
|
|
||||||
expectNodePorts []int
|
|
||||||
}{{
|
|
||||||
svc: svctest.MakeService("foo1",
|
|
||||||
svctest.SetTypeNodePort,
|
|
||||||
svctest.SetPorts(
|
|
||||||
svctest.MakeServicePort("port-tcp", 53, intstr.FromInt(6503), api.ProtocolTCP),
|
|
||||||
svctest.MakeServicePort("port-udp", 53, intstr.FromInt(6503), api.ProtocolUDP)),
|
|
||||||
svctest.SetNodePorts(30053, 30053)),
|
|
||||||
name: "foo1",
|
|
||||||
expectNodePorts: []int{30053, 30053},
|
|
||||||
}, {
|
|
||||||
svc: svctest.MakeService("foo2",
|
|
||||||
svctest.SetTypeNodePort,
|
|
||||||
svctest.SetPorts(
|
|
||||||
svctest.MakeServicePort("port-tcp", 54, intstr.FromInt(6504), api.ProtocolTCP),
|
|
||||||
svctest.MakeServicePort("port-udp", 54, intstr.FromInt(6504), api.ProtocolUDP)),
|
|
||||||
svctest.SetNodePorts(30054, 30054)),
|
|
||||||
name: "foo2",
|
|
||||||
expectNodePorts: []int{30054, 30054},
|
|
||||||
}, {
|
|
||||||
svc: svctest.MakeService("foo3",
|
|
||||||
svctest.SetTypeNodePort,
|
|
||||||
svctest.SetPorts(
|
|
||||||
svctest.MakeServicePort("port-tcp", 55, intstr.FromInt(6505), api.ProtocolTCP),
|
|
||||||
svctest.MakeServicePort("port-udp", 55, intstr.FromInt(6506), api.ProtocolUDP)),
|
|
||||||
svctest.SetNodePorts(30055, 30056)),
|
|
||||||
name: "foo3",
|
|
||||||
expectNodePorts: []int{30055, 30056},
|
|
||||||
}}
|
|
||||||
|
|
||||||
ctx := genericapirequest.NewDefaultContext()
|
|
||||||
for _, test := range testCases {
|
|
||||||
createdSvc, err := storage.Create(ctx, test.svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
createdService := createdSvc.(*api.Service)
|
|
||||||
objMeta, err := meta.Accessor(createdService)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if !metav1.HasObjectMetaSystemFieldValues(objMeta) {
|
|
||||||
t.Errorf("storage did not populate object meta field values")
|
|
||||||
}
|
|
||||||
if createdService.Name != test.name {
|
|
||||||
t.Errorf("Expected %s, but got %s", test.name, createdService.Name)
|
|
||||||
}
|
|
||||||
serviceNodePorts := collectServiceNodePorts(createdService)
|
|
||||||
if !reflect.DeepEqual(serviceNodePorts, test.expectNodePorts) {
|
|
||||||
t.Errorf("Expected %v, but got %v", test.expectNodePorts, serviceNodePorts)
|
|
||||||
}
|
|
||||||
srv, err := getService(storage, ctx, test.name, &metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if srv == nil {
|
|
||||||
t.Fatalf("Failed to find service: %s", test.name)
|
|
||||||
}
|
|
||||||
for i := range serviceNodePorts {
|
|
||||||
nodePort := serviceNodePorts[i]
|
|
||||||
// Release the node port at the end of the test case.
|
|
||||||
storage.alloc.serviceNodePorts.Release(nodePort)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestServiceRegistryUpdate(t *testing.T) {
|
func TestServiceRegistryUpdate(t *testing.T) {
|
||||||
ctx := genericapirequest.NewDefaultContext()
|
ctx := genericapirequest.NewDefaultContext()
|
||||||
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
|
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
|
||||||
@ -1427,90 +1353,6 @@ func TestServiceRegistryInternalTrafficPolicyLocalThenCluster(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateInitNodePorts(t *testing.T) {
|
|
||||||
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
|
|
||||||
defer server.Terminate(t)
|
|
||||||
nodePortOp := portallocator.StartOperation(storage.alloc.serviceNodePorts, false)
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
service *api.Service
|
|
||||||
expectSpecifiedNodePorts []int
|
|
||||||
}{{
|
|
||||||
name: "Service doesn't have specified NodePort",
|
|
||||||
service: svctest.MakeService("foo", svctest.SetTypeNodePort),
|
|
||||||
expectSpecifiedNodePorts: []int{},
|
|
||||||
}, {
|
|
||||||
name: "Service has one specified NodePort",
|
|
||||||
service: svctest.MakeService("foo",
|
|
||||||
svctest.SetTypeNodePort,
|
|
||||||
svctest.SetPorts(
|
|
||||||
svctest.MakeServicePort("port-tcp", 53, intstr.FromInt(6502), api.ProtocolTCP)),
|
|
||||||
svctest.SetNodePorts(30053)),
|
|
||||||
expectSpecifiedNodePorts: []int{30053},
|
|
||||||
}, {
|
|
||||||
name: "Service has two same ports with different protocols and specifies same NodePorts",
|
|
||||||
service: svctest.MakeService("foo",
|
|
||||||
svctest.SetTypeNodePort,
|
|
||||||
svctest.SetPorts(
|
|
||||||
svctest.MakeServicePort("port-tcp", 53, intstr.FromInt(6502), api.ProtocolTCP),
|
|
||||||
svctest.MakeServicePort("port-udp", 53, intstr.FromInt(6502), api.ProtocolUDP)),
|
|
||||||
svctest.SetNodePorts(30054, 30054)),
|
|
||||||
expectSpecifiedNodePorts: []int{30054, 30054},
|
|
||||||
}, {
|
|
||||||
name: "Service has two same ports with different protocols and specifies different NodePorts",
|
|
||||||
service: svctest.MakeService("foo",
|
|
||||||
svctest.SetTypeNodePort,
|
|
||||||
svctest.SetPorts(
|
|
||||||
svctest.MakeServicePort("port-tcp", 53, intstr.FromInt(6502), api.ProtocolTCP),
|
|
||||||
svctest.MakeServicePort("port-udp", 53, intstr.FromInt(6502), api.ProtocolUDP)),
|
|
||||||
svctest.SetNodePorts(30055, 30056)),
|
|
||||||
expectSpecifiedNodePorts: []int{30055, 30056},
|
|
||||||
}, {
|
|
||||||
name: "Service has two different ports with different protocols and specifies different NodePorts",
|
|
||||||
service: svctest.MakeService("foo",
|
|
||||||
svctest.SetTypeNodePort,
|
|
||||||
svctest.SetPorts(
|
|
||||||
svctest.MakeServicePort("port-tcp", 53, intstr.FromInt(6502), api.ProtocolTCP),
|
|
||||||
svctest.MakeServicePort("port-udp", 54, intstr.FromInt(6502), api.ProtocolUDP)),
|
|
||||||
svctest.SetNodePorts(30057, 30058)),
|
|
||||||
expectSpecifiedNodePorts: []int{30057, 30058},
|
|
||||||
}, {
|
|
||||||
name: "Service has two same ports with different protocols but only specifies one NodePort",
|
|
||||||
service: svctest.MakeService("foo",
|
|
||||||
svctest.SetTypeNodePort,
|
|
||||||
svctest.SetPorts(
|
|
||||||
svctest.MakeServicePort("port-tcp", 53, intstr.FromInt(6502), api.ProtocolTCP),
|
|
||||||
svctest.MakeServicePort("port-udp", 53, intstr.FromInt(6502), api.ProtocolUDP)),
|
|
||||||
svctest.SetNodePorts(30059)),
|
|
||||||
expectSpecifiedNodePorts: []int{30059, 30059},
|
|
||||||
}}
|
|
||||||
|
|
||||||
for _, test := range testCases {
|
|
||||||
err := initNodePorts(test.service, nodePortOp)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%q: unexpected error: %v", test.name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceNodePorts := collectServiceNodePorts(test.service)
|
|
||||||
if len(test.expectSpecifiedNodePorts) == 0 {
|
|
||||||
for _, nodePort := range serviceNodePorts {
|
|
||||||
if !storage.alloc.serviceNodePorts.Has(nodePort) {
|
|
||||||
t.Errorf("%q: unexpected NodePort %d, out of range", test.name, nodePort)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if !reflect.DeepEqual(serviceNodePorts, test.expectSpecifiedNodePorts) {
|
|
||||||
t.Errorf("%q: expected NodePorts %v, but got %v", test.name, test.expectSpecifiedNodePorts, serviceNodePorts)
|
|
||||||
}
|
|
||||||
for i := range serviceNodePorts {
|
|
||||||
nodePort := serviceNodePorts[i]
|
|
||||||
// Release the node port at the end of the test case.
|
|
||||||
storage.alloc.serviceNodePorts.Release(nodePort)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUpdateNodePorts(t *testing.T) {
|
func TestUpdateNodePorts(t *testing.T) {
|
||||||
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
|
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
|
||||||
defer server.Terminate(t)
|
defer server.Terminate(t)
|
||||||
|
@ -4733,6 +4733,399 @@ func TestCreateInitIPFields(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCreateInitNodePorts(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
svc *api.Service
|
||||||
|
expectError bool
|
||||||
|
expectNodePorts bool
|
||||||
|
gateMixedProtocolLBService bool
|
||||||
|
gateServiceLBNodePortControl bool
|
||||||
|
}{{
|
||||||
|
name: "type:ExternalName",
|
||||||
|
svc: svctest.MakeService("foo"),
|
||||||
|
expectNodePorts: false,
|
||||||
|
}, {
|
||||||
|
name: "type:ExternalName_with_NodePorts",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetUniqueNodePorts),
|
||||||
|
expectError: true,
|
||||||
|
}, {
|
||||||
|
name: "type:ClusterIP",
|
||||||
|
svc: svctest.MakeService("foo"),
|
||||||
|
expectNodePorts: false,
|
||||||
|
}, {
|
||||||
|
name: "type:ClusterIP_with_NodePorts",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetUniqueNodePorts),
|
||||||
|
expectError: true,
|
||||||
|
}, {
|
||||||
|
name: "type:NodePort_single_port_unspecified",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeNodePort),
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:NodePort_single_port_specified",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeNodePort, svctest.SetUniqueNodePorts),
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:NodePort_multiport_unspecified",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeNodePort,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 80, intstr.FromInt(80), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 443, intstr.FromInt(443), api.ProtocolTCP))),
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:NodePort_multiport_specified",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeNodePort,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 80, intstr.FromInt(80), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 443, intstr.FromInt(443), api.ProtocolTCP)),
|
||||||
|
svctest.SetUniqueNodePorts),
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:NodePort_multiport_same",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeNodePort,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 80, intstr.FromInt(80), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 443, intstr.FromInt(443), api.ProtocolTCP)),
|
||||||
|
svctest.SetNodePorts(30080, 30080)),
|
||||||
|
expectError: true,
|
||||||
|
}, {
|
||||||
|
name: "type:NodePort_multiport_multiproto_unspecified",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeNodePort,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 53, intstr.FromInt(53), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 53, intstr.FromInt(53), api.ProtocolUDP))),
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:NodePort_multiport_multiproto_specified",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeNodePort,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 53, intstr.FromInt(53), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 53, intstr.FromInt(53), api.ProtocolUDP)),
|
||||||
|
svctest.SetUniqueNodePorts),
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:NodePort_multiport_multiproto_same",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeNodePort,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 53, intstr.FromInt(53), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 53, intstr.FromInt(53), api.ProtocolUDP)),
|
||||||
|
svctest.SetNodePorts(30053, 30053)),
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:NodePort_multiport_multiproto_conflict",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeNodePort,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 93, intstr.FromInt(93), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 76, intstr.FromInt(76), api.ProtocolUDP)),
|
||||||
|
svctest.SetNodePorts(30093, 30093)),
|
||||||
|
expectError: true,
|
||||||
|
}, {
|
||||||
|
// When the ServiceLBNodePortControl gate is locked, this can be removed.
|
||||||
|
name: "type:LoadBalancer_single_port_unspecified_gateServiceLBNodePortControl:off_alloc:nil",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer),
|
||||||
|
gateServiceLBNodePortControl: false,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
// When the ServiceLBNodePortControl gate is locked, this can be removed.
|
||||||
|
name: "type:LoadBalancer_single_port_unspecified_gateServiceLBNodePortControl:off_alloc:false",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetAllocateLoadBalancerNodePorts(false)),
|
||||||
|
gateServiceLBNodePortControl: false,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
// When the ServiceLBNodePortControl gate is locked, this can be removed.
|
||||||
|
name: "type:LoadBalancer_single_port_unspecified_gateServiceLBNodePortControl:off_alloc:true",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetAllocateLoadBalancerNodePorts(true)),
|
||||||
|
gateServiceLBNodePortControl: false,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
// When the ServiceLBNodePortControl gate is locked, this can be removed.
|
||||||
|
name: "type:LoadBalancer_single_port_specified_gateServiceLBNodePortControl:off",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer, svctest.SetUniqueNodePorts),
|
||||||
|
gateServiceLBNodePortControl: false,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
// When the ServiceLBNodePortControl gate is locked, this can be removed.
|
||||||
|
name: "type:LoadBalancer_multiport_unspecified_gateServiceLBNodePortControl:off",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 80, intstr.FromInt(80), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 443, intstr.FromInt(443), api.ProtocolTCP))),
|
||||||
|
gateServiceLBNodePortControl: false,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
// When the ServiceLBNodePortControl gate is locked, this can be removed.
|
||||||
|
name: "type:LoadBalancer_multiport_specified_gateServiceLBNodePortControl:off",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 80, intstr.FromInt(80), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 443, intstr.FromInt(443), api.ProtocolTCP)),
|
||||||
|
svctest.SetUniqueNodePorts),
|
||||||
|
gateServiceLBNodePortControl: false,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_single_port_unspecified_gateServiceLBNodePortControl:on_alloc:false",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetAllocateLoadBalancerNodePorts(false)),
|
||||||
|
gateServiceLBNodePortControl: true,
|
||||||
|
expectNodePorts: false,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_single_port_unspecified_gateServiceLBNodePortControl:on_alloc:true",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetAllocateLoadBalancerNodePorts(true)),
|
||||||
|
gateServiceLBNodePortControl: true,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_single_port_specified_gateServiceLBNodePortControl:on_alloc:false",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetUniqueNodePorts,
|
||||||
|
svctest.SetAllocateLoadBalancerNodePorts(false)),
|
||||||
|
gateServiceLBNodePortControl: true,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_single_port_specified_gateServiceLBNodePortControl:on_alloc:true",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetUniqueNodePorts,
|
||||||
|
svctest.SetAllocateLoadBalancerNodePorts(true)),
|
||||||
|
gateServiceLBNodePortControl: true,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_multiport_unspecified_gateServiceLBNodePortControl:on_alloc:false",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 80, intstr.FromInt(80), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 443, intstr.FromInt(443), api.ProtocolTCP)),
|
||||||
|
svctest.SetAllocateLoadBalancerNodePorts(false)),
|
||||||
|
gateServiceLBNodePortControl: true,
|
||||||
|
expectNodePorts: false,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_multiport_unspecified_gateServiceLBNodePortControl:on_alloc:true",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 80, intstr.FromInt(80), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 443, intstr.FromInt(443), api.ProtocolTCP)),
|
||||||
|
svctest.SetAllocateLoadBalancerNodePorts(true)),
|
||||||
|
gateServiceLBNodePortControl: true,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_multiport_specified_gateServiceLBNodePortControl:on_alloc:false",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 80, intstr.FromInt(80), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 443, intstr.FromInt(443), api.ProtocolTCP)),
|
||||||
|
svctest.SetUniqueNodePorts,
|
||||||
|
svctest.SetAllocateLoadBalancerNodePorts(false)),
|
||||||
|
gateServiceLBNodePortControl: true,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_multiport_specified_gateServiceLBNodePortControl:on_alloc:true",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 80, intstr.FromInt(80), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 443, intstr.FromInt(443), api.ProtocolTCP)),
|
||||||
|
svctest.SetUniqueNodePorts,
|
||||||
|
svctest.SetAllocateLoadBalancerNodePorts(true)),
|
||||||
|
gateServiceLBNodePortControl: true,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_multiport_same",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 80, intstr.FromInt(80), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 443, intstr.FromInt(443), api.ProtocolTCP)),
|
||||||
|
svctest.SetNodePorts(30080, 30080)),
|
||||||
|
expectError: true,
|
||||||
|
}, {
|
||||||
|
// When the MixedProtocolLBService gate is locked, this can be removed.
|
||||||
|
name: "type:LoadBalancer_multiport_multiproto_unspecified_MixedProtocolLBService:off",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 53, intstr.FromInt(53), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 53, intstr.FromInt(53), api.ProtocolUDP))),
|
||||||
|
gateMixedProtocolLBService: false,
|
||||||
|
expectError: true,
|
||||||
|
}, {
|
||||||
|
// When the MixedProtocolLBService gate is locked, this can be removed.
|
||||||
|
name: "type:LoadBalancer_multiport_multiproto_specified_MixedProtocolLBService:off",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 53, intstr.FromInt(53), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 53, intstr.FromInt(53), api.ProtocolUDP)),
|
||||||
|
svctest.SetUniqueNodePorts),
|
||||||
|
gateMixedProtocolLBService: false,
|
||||||
|
expectError: true,
|
||||||
|
}, {
|
||||||
|
// When the MixedProtocolLBService gate is locked, this can be removed.
|
||||||
|
name: "type:LoadBalancer_multiport_multiproto_same_MixedProtocolLBService:off",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 53, intstr.FromInt(53), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 53, intstr.FromInt(53), api.ProtocolUDP)),
|
||||||
|
svctest.SetNodePorts(30053, 30053)),
|
||||||
|
gateMixedProtocolLBService: false,
|
||||||
|
expectError: true,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_multiport_multiproto_unspecified_MixedProtocolLBService:on",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 53, intstr.FromInt(53), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 53, intstr.FromInt(53), api.ProtocolUDP))),
|
||||||
|
gateMixedProtocolLBService: true,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_multiport_multiproto_specified_MixedProtocolLBService:on",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 53, intstr.FromInt(53), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 53, intstr.FromInt(53), api.ProtocolUDP)),
|
||||||
|
svctest.SetUniqueNodePorts),
|
||||||
|
gateMixedProtocolLBService: true,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_multiport_multiproto_same_MixedProtocolLBService:on",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 53, intstr.FromInt(53), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 53, intstr.FromInt(53), api.ProtocolUDP)),
|
||||||
|
svctest.SetNodePorts(30053, 30053)),
|
||||||
|
gateMixedProtocolLBService: true,
|
||||||
|
expectNodePorts: true,
|
||||||
|
}, {
|
||||||
|
name: "type:LoadBalancer_multiport_multiproto_conflict",
|
||||||
|
svc: svctest.MakeService("foo",
|
||||||
|
svctest.SetTypeLoadBalancer,
|
||||||
|
svctest.SetPorts(
|
||||||
|
svctest.MakeServicePort("p", 93, intstr.FromInt(93), api.ProtocolTCP),
|
||||||
|
svctest.MakeServicePort("q", 76, intstr.FromInt(76), api.ProtocolUDP)),
|
||||||
|
svctest.SetNodePorts(30093, 30093)),
|
||||||
|
expectError: true,
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Do this in the outer scope for performance.
|
||||||
|
storage, _, server := newStorage(t, []api.IPFamily{api.IPv4Protocol})
|
||||||
|
defer server.Terminate(t)
|
||||||
|
defer storage.Store.DestroyFunc()
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServiceLBNodePortControl, tc.gateServiceLBNodePortControl)()
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.MixedProtocolLBService, tc.gateMixedProtocolLBService)()
|
||||||
|
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
ctx := genericapirequest.NewDefaultContext()
|
||||||
|
createdObj, err := storage.Create(ctx, tc.svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||||
|
if tc.expectError && err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error creating service: %v", err)
|
||||||
|
}
|
||||||
|
defer storage.Delete(ctx, tc.svc.Name, rest.ValidateAllObjectFunc, &metav1.DeleteOptions{})
|
||||||
|
if tc.expectError && err == nil {
|
||||||
|
t.Fatalf("unexpected success creating service")
|
||||||
|
}
|
||||||
|
createdSvc := createdObj.(*api.Service)
|
||||||
|
//FIXME: HACK!! Delete above calls "inner" which doesn't
|
||||||
|
// yet call the allocators - no release = alloc errors!
|
||||||
|
defer func() {
|
||||||
|
for _, al := range storage.alloc.serviceIPAllocatorsByFamily {
|
||||||
|
for _, ip := range createdSvc.Spec.ClusterIPs {
|
||||||
|
al.Release(netutils.ParseIPSloppy(ip))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, p := range createdSvc.Spec.Ports {
|
||||||
|
storage.alloc.serviceNodePorts.Release(int(p.NodePort))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Produce a map of port index to nodeport value, excluding zero.
|
||||||
|
ports := map[int]*api.ServicePort{}
|
||||||
|
for i := range createdSvc.Spec.Ports {
|
||||||
|
p := &createdSvc.Spec.Ports[i]
|
||||||
|
if p.NodePort != 0 {
|
||||||
|
ports[i] = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.expectNodePorts && len(ports) == 0 {
|
||||||
|
t.Fatalf("expected NodePorts to be allocated, found none")
|
||||||
|
}
|
||||||
|
if !tc.expectNodePorts && len(ports) > 0 {
|
||||||
|
t.Fatalf("expected NodePorts to not be allocated, found %v", ports)
|
||||||
|
}
|
||||||
|
if !tc.expectNodePorts {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we got the right number of allocations
|
||||||
|
if want, got := len(ports), len(tc.svc.Spec.Ports); want != got {
|
||||||
|
t.Fatalf("expected %d NodePorts, found %d", want, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure they are all allocated
|
||||||
|
for _, p := range ports {
|
||||||
|
if !portIsAllocated(t, storage.alloc.serviceNodePorts, p.NodePort) {
|
||||||
|
t.Errorf("expected port to be allocated: %v", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we got any specific allocations
|
||||||
|
for i, p := range tc.svc.Spec.Ports {
|
||||||
|
if p.NodePort != 0 {
|
||||||
|
if ports[i].NodePort != p.NodePort {
|
||||||
|
t.Errorf("expected Ports[%d].NodePort to be %d, got %d", i, p.NodePort, ports[i].NodePort)
|
||||||
|
}
|
||||||
|
// Remove requested ports from the set
|
||||||
|
delete(ports, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure any allocated ports are unique
|
||||||
|
seen := map[int32]int32{}
|
||||||
|
for i, p := range ports {
|
||||||
|
// We allow the same NodePort for different protocols of the
|
||||||
|
// same Port.
|
||||||
|
if prev, found := seen[p.NodePort]; found && prev != p.Port {
|
||||||
|
t.Errorf("found non-unique allocation in Ports[%d].NodePort: %d -> %d", i, p.NodePort, p.Port)
|
||||||
|
}
|
||||||
|
seen[p.NodePort] = p.Port
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Prove that a dry-run create doesn't actually allocate IPs or ports.
|
// Prove that a dry-run create doesn't actually allocate IPs or ports.
|
||||||
func TestCreateDryRun(t *testing.T) {
|
func TestCreateDryRun(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user