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:
Tim Hockin 2021-07-03 16:58:50 -07:00
parent 46d7289655
commit 2212924a96
2 changed files with 393 additions and 158 deletions

View File

@ -25,7 +25,6 @@ import (
"testing"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
@ -288,79 +287,6 @@ func makeIPNet6(t *testing.T) *net.IPNet {
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) {
ctx := genericapirequest.NewDefaultContext()
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) {
storage, server := NewTestREST(t, []api.IPFamily{api.IPv4Protocol})
defer server.Terminate(t)

View File

@ -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.
func TestCreateDryRun(t *testing.T) {
testCases := []struct {