Merge pull request #94728 from amorenoz/portforward_udp

kubectl: Fix TCP and UDP port forward

Kubernetes-commit: 28fc772d3609694aff8c0704a39185227c7ae939
This commit is contained in:
Kubernetes Publisher 2020-09-16 16:14:46 -07:00
commit 00e703ea95
5 changed files with 48 additions and 18 deletions

4
Godeps/Godeps.json generated
View File

@ -764,7 +764,7 @@
}, },
{ {
"ImportPath": "k8s.io/apimachinery", "ImportPath": "k8s.io/apimachinery",
"Rev": "2f44a17e43a6" "Rev": "714f1137f89b"
}, },
{ {
"ImportPath": "k8s.io/cli-runtime", "ImportPath": "k8s.io/cli-runtime",
@ -772,7 +772,7 @@
}, },
{ {
"ImportPath": "k8s.io/client-go", "ImportPath": "k8s.io/client-go",
"Rev": "a32e6027fa67" "Rev": "cba7285b7f29"
}, },
{ {
"ImportPath": "k8s.io/code-generator", "ImportPath": "k8s.io/code-generator",

8
go.mod
View File

@ -35,9 +35,9 @@ require (
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4
gopkg.in/yaml.v2 v2.2.8 gopkg.in/yaml.v2 v2.2.8
k8s.io/api v0.0.0-20200914174313-52bf62410745 k8s.io/api v0.0.0-20200914174313-52bf62410745
k8s.io/apimachinery v0.0.0-20200915234101-2f44a17e43a6 k8s.io/apimachinery v0.0.0-20200916235632-714f1137f89b
k8s.io/cli-runtime v0.0.0-20200915100420-3cc3835b3ec2 k8s.io/cli-runtime v0.0.0-20200915100420-3cc3835b3ec2
k8s.io/client-go v0.0.0-20200915085750-a32e6027fa67 k8s.io/client-go v0.0.0-20200917000235-cba7285b7f29
k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f
k8s.io/klog/v2 v2.2.0 k8s.io/klog/v2 v2.2.0
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6
@ -49,9 +49,9 @@ require (
replace ( replace (
k8s.io/api => k8s.io/api v0.0.0-20200914174313-52bf62410745 k8s.io/api => k8s.io/api v0.0.0-20200914174313-52bf62410745
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20200915234101-2f44a17e43a6 k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20200916235632-714f1137f89b
k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20200915100420-3cc3835b3ec2 k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20200915100420-3cc3835b3ec2
k8s.io/client-go => k8s.io/client-go v0.0.0-20200915085750-a32e6027fa67 k8s.io/client-go => k8s.io/client-go v0.0.0-20200917000235-cba7285b7f29
k8s.io/code-generator => k8s.io/code-generator v0.0.0-20200904030940-4116974d9b44 k8s.io/code-generator => k8s.io/code-generator v0.0.0-20200904030940-4116974d9b44
k8s.io/component-base => k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f k8s.io/component-base => k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f
k8s.io/metrics => k8s.io/metrics v0.0.0-20200909174239-935813ae0d59 k8s.io/metrics => k8s.io/metrics v0.0.0-20200909174239-935813ae0d59

4
go.sum
View File

@ -504,9 +504,9 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
k8s.io/api v0.0.0-20200914174313-52bf62410745/go.mod h1:UT3vnXQcd48N6K0IuGGYk1ufh1lolzq+pC4aE2BPvWA= k8s.io/api v0.0.0-20200914174313-52bf62410745/go.mod h1:UT3vnXQcd48N6K0IuGGYk1ufh1lolzq+pC4aE2BPvWA=
k8s.io/apimachinery v0.0.0-20200915234101-2f44a17e43a6/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.0.0-20200916235632-714f1137f89b/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
k8s.io/cli-runtime v0.0.0-20200915100420-3cc3835b3ec2/go.mod h1:Hma9QauilauA4Azq48kPjOcZNafcVy3yUE7iiJUT8QQ= k8s.io/cli-runtime v0.0.0-20200915100420-3cc3835b3ec2/go.mod h1:Hma9QauilauA4Azq48kPjOcZNafcVy3yUE7iiJUT8QQ=
k8s.io/client-go v0.0.0-20200915085750-a32e6027fa67/go.mod h1:l+k6PpRBFWMCiLvf6k6opk7J/clbXd38cNBOo7k6jQg= k8s.io/client-go v0.0.0-20200917000235-cba7285b7f29/go.mod h1:Plj2rfLmeMYfAMuMgA/1EGuUaDxt78tvB9yfdi6fg6A=
k8s.io/code-generator v0.0.0-20200904030940-4116974d9b44/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/code-generator v0.0.0-20200904030940-4116974d9b44/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk=
k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f/go.mod h1:KLUf6+rBAAlh4P5aX9t725mVdFgvY6LfYzl+QOveAV4= k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f/go.mod h1:KLUf6+rBAAlh4P5aX9t725mVdFgvY6LfYzl+QOveAV4=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=

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 // checkUDPPortInService returns an error if remote port in Service is a UDP port
// TODO: remove this check after #47862 is solved // TODO: remove this check after #47862 is solved
func checkUDPPortInService(ports []string, svc *corev1.Service) error { func checkUDPPortInService(ports []string, svc *corev1.Service) error {
udpOnlyPorts := sets.NewInt() udpPorts := sets.NewInt()
tcpPorts := sets.NewInt()
for _, port := range svc.Spec.Ports { for _, port := range svc.Spec.Ports {
portNum := int(port.Port) portNum := int(port.Port)
switch port.Protocol { switch port.Protocol {
case corev1.ProtocolUDP: case corev1.ProtocolUDP:
udpOnlyPorts.Insert(portNum) udpPorts.Insert(portNum)
case corev1.ProtocolTCP: 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 // checkUDPPortInPod returns an error if remote port in Pod is a UDP port
// TODO: remove this check after #47862 is solved // TODO: remove this check after #47862 is solved
func checkUDPPortInPod(ports []string, pod *corev1.Pod) error { func checkUDPPortInPod(ports []string, pod *corev1.Pod) error {
udpOnlyPorts := sets.NewInt() udpPorts := sets.NewInt()
tcpPorts := sets.NewInt()
for _, ct := range pod.Spec.Containers { for _, ct := range pod.Spec.Containers {
for _, ctPort := range ct.Ports { for _, ctPort := range ct.Ports {
portNum := int(ctPort.ContainerPort) portNum := int(ctPort.ContainerPort)
switch ctPort.Protocol { switch ctPort.Protocol {
case corev1.ProtocolUDP: case corev1.ProtocolUDP:
udpOnlyPorts.Insert(portNum) udpPorts.Insert(portNum)
case corev1.ProtocolTCP: 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. // Complete completes all the required options for port-forward cmd.

View File

@ -880,7 +880,7 @@ func TestCheckUDPPort(t *testing.T) {
expectError: true, 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{ pod: &corev1.Pod{
Spec: corev1.PodSpec{ Spec: corev1.PodSpec{
Containers: []corev1.Container{ Containers: []corev1.Container{
@ -895,6 +895,22 @@ func TestCheckUDPPort(t *testing.T) {
}, },
ports: []string{":53"}, 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", name: "forward to a UDP port in a Service",
@ -921,7 +937,7 @@ func TestCheckUDPPort(t *testing.T) {
expectError: true, 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{ service: &corev1.Service{
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{ Ports: []corev1.ServicePort{
@ -932,6 +948,18 @@ func TestCheckUDPPort(t *testing.T) {
}, },
ports: []string{"53"}, 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 { for _, tc := range tests {
var err error var err error