Code change:
Similar to
is a dup of this. PR is just a quick try. Will spend more time on it to cover all cases.
status?
I sent PR which is waiting for reviewing from . Also, that PR is blocked by issue which is self-assigned by you but not fixed yet :)
That issue might be not hard to fix, but I didn't find how.So I need your help. IMO, we mignt need to change CI jobs configure in some files or images.
After discussing with reviewer ( this might be better suited to merge but not for 1.7.0, as it touches a part of the code that is quite old and stable. In other words, we probably need to give this change some time to soak in the e2e system as opposed to put right away into the release.

Related discussion:
text: if test.name == "Allocate specified ClusterIP" && test.svc.Spec.ClusterIP != "1.2.3.4" { t.Errorf("%q: expected ClusterIP %q, but got %q", test.name, "1.2.3.4", test.svc.Spec.ClusterIP) } <ins> if hasAllocatedIP { if helper.IsServiceIPSet(test.svc) { storage.serviceIPs.Release(net.ParseIP(test.svc.Spec.ClusterIP)) } } } } func TestInitNodePorts(t *testing.T) { storage, _ := NewTestREST(t, nil) nodePortOp := portallocator.StartOperation(storage.serviceNodePorts) defer nodePortOp.Finish() testCases := []struct { name                     string service                  *api.Service expectSpecifiedNodePorts []int }{ { name: "Service doesn't have specified NodePort", service: &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Type:     api.ServiceTypeNodePort, Ports: []api.ServicePort{ { Name:       "port-tcp", Port:       53, TargetPort: intstr.FromInt(6502), Protocol:   api.ProtocolTCP, }, }, }, }, expectSpecifiedNodePorts: []int{}, }, { name: "Service has one specified NodePort", service: &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Type:     api.ServiceTypeNodePort, Ports: []api.ServicePort{{ Name:       "port-tcp", Port:       53, TargetPort: intstr.FromInt(6502), Protocol:   api.ProtocolTCP, NodePort:   30053, }}, }, }, expectSpecifiedNodePorts: []int{30053}, }, { name: "Service has two same ports with different protocols and specifies same NodePorts", service: &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Type:     api.ServiceTypeNodePort, Ports: []api.ServicePort{ { Name:       "port-tcp", Port:       53, TargetPort: intstr.FromInt(6502), Protocol:   api.ProtocolTCP, NodePort:   30054, }, { Name:       "port-udp", Port:       53, TargetPort: intstr.FromInt(6502), Protocol:   api.ProtocolUDP, NodePort:   30054, }, }, }, }, expectSpecifiedNodePorts: []int{30054, 30054}, }, { name: "Service has two same ports with different protocols and specifies different NodePorts", service: &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Type:     api.ServiceTypeNodePort, Ports: []api.ServicePort{ { Name:       "port-tcp", Port:       53, TargetPort: intstr.FromInt(6502), Protocol:   api.ProtocolTCP, NodePort:   30055, }, { Name:       "port-udp", Port:       53, TargetPort: intstr.FromInt(6502), Protocol:   api.ProtocolUDP, NodePort:   30056, }, }, }, }, expectSpecifiedNodePorts: []int{30055, 30056}, }, { name: "Service has two different ports with different protocols and specifies different NodePorts", service: &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Type:     api.ServiceTypeNodePort, Ports: []api.ServicePort{ { Name:       "port-tcp", Port:       53, TargetPort: intstr.FromInt(6502), Protocol:   api.ProtocolTCP, NodePort:   30057, }, { Name:       "port-udp", Port:       54, TargetPort: intstr.FromInt(6502), Protocol:   api.ProtocolUDP, NodePort:   30058, }, }, }, }, expectSpecifiedNodePorts: []int{30057, 30058}, }, { name: "Service has two same ports with different protocols but only specifies one NodePort", service: &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Type:     api.ServiceTypeNodePort, Ports: []api.ServicePort{ { Name:       "port-tcp", Port:       53, TargetPort: intstr.FromInt(6502), Protocol:   api.ProtocolTCP, NodePort:   30059, }, { Name:       "port-udp", Port:       53, TargetPort: intstr.FromInt(6502), Protocol:   api.ProtocolUDP, }, }, }, }, expectSpecifiedNodePorts: []int{30059, 30059}, }, } for _, test := range testCases { err := storage.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.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) } </ins> } } <del> func TestUpdateNodePort(t *testing.T) { </del> <ins> func TestUpdateNodePorts(t *testing.T) { </ins> storage, _ := NewTestREST(t, nil) nodePortOp := portallocator.StartOperation(storage.serviceNodePorts) defer nodePortOp.Finish()