portforward: Fix UDP-only ports calculation

If a service has both TCP and UDP but the TCP port appears before in the
range loop, it will be considered a UDP-only port and the forwarding
will fail.

Fix that by calculating the difference between UDP ports and TCP ports.

Signed-off-by: Adrian Moreno <amorenoz@redhat.com>

Kubernetes-commit: c194bc85319298e7c2fd002031d0ff23ded54591
This commit is contained in:
Adrian Moreno 2020-09-11 19:50:11 +02:00 committed by Kubernetes Publisher
parent 85e60022bb
commit 92ea032f08
2 changed files with 40 additions and 10 deletions

View File

@ -260,35 +260,37 @@ func checkUDPPorts(udpOnlyPorts sets.Int, ports []string, obj metav1.Object) err
// checkUDPPortInService returns an error if remote port in Service is a UDP port
// TODO: remove this check after #47862 is solved
func checkUDPPortInService(ports []string, svc *corev1.Service) error {
udpOnlyPorts := sets.NewInt()
udpPorts := sets.NewInt()
tcpPorts := sets.NewInt()
for _, port := range svc.Spec.Ports {
portNum := int(port.Port)
switch port.Protocol {
case corev1.ProtocolUDP:
udpOnlyPorts.Insert(portNum)
udpPorts.Insert(portNum)
case corev1.ProtocolTCP:
udpOnlyPorts.Delete(portNum)
tcpPorts.Insert(portNum)
}
}
return checkUDPPorts(udpOnlyPorts, ports, svc)
return checkUDPPorts(udpPorts.Difference(tcpPorts), ports, svc)
}
// checkUDPPortInPod returns an error if remote port in Pod is a UDP port
// TODO: remove this check after #47862 is solved
func checkUDPPortInPod(ports []string, pod *corev1.Pod) error {
udpOnlyPorts := sets.NewInt()
udpPorts := sets.NewInt()
tcpPorts := sets.NewInt()
for _, ct := range pod.Spec.Containers {
for _, ctPort := range ct.Ports {
portNum := int(ctPort.ContainerPort)
switch ctPort.Protocol {
case corev1.ProtocolUDP:
udpOnlyPorts.Insert(portNum)
udpPorts.Insert(portNum)
case corev1.ProtocolTCP:
udpOnlyPorts.Delete(portNum)
tcpPorts.Insert(portNum)
}
}
}
return checkUDPPorts(udpOnlyPorts, ports, pod)
return checkUDPPorts(udpPorts.Difference(tcpPorts), ports, pod)
}
// Complete completes all the required options for port-forward cmd.

View File

@ -880,7 +880,7 @@ func TestCheckUDPPort(t *testing.T) {
expectError: true,
},
{
name: "Pod has ports with both TCP and UDP protocol",
name: "Pod has ports with both TCP and UDP protocol (UDP first)",
pod: &corev1.Pod{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
@ -895,6 +895,22 @@ func TestCheckUDPPort(t *testing.T) {
},
ports: []string{":53"},
},
{
name: "Pod has ports with both TCP and UDP protocol (TCP first)",
pod: &corev1.Pod{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Ports: []corev1.ContainerPort{
{Protocol: corev1.ProtocolTCP, ContainerPort: 53},
{Protocol: corev1.ProtocolUDP, ContainerPort: 53},
},
},
},
},
},
ports: []string{":53"},
},
{
name: "forward to a UDP port in a Service",
@ -921,7 +937,7 @@ func TestCheckUDPPort(t *testing.T) {
expectError: true,
},
{
name: "Service has ports with both TCP and UDP protocol",
name: "Service has ports with both TCP and UDP protocol (UDP first)",
service: &corev1.Service{
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
@ -932,6 +948,18 @@ func TestCheckUDPPort(t *testing.T) {
},
ports: []string{"53"},
},
{
name: "Service has ports with both TCP and UDP protocol (TCP first)",
service: &corev1.Service{
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
{Protocol: corev1.ProtocolTCP, Port: 53},
{Protocol: corev1.ProtocolUDP, Port: 53},
},
},
},
ports: []string{"53"},
},
}
for _, tc := range tests {
var err error