Fix concatenation of IPv6 addresses and ports

This commit is contained in:
Harold Ozouf 2020-12-04 20:56:04 +01:00 committed by GitHub
parent 121eaced49
commit 7403b6fb82
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 403 additions and 11 deletions

View file

@ -119,6 +119,35 @@ subsets:
- name: websecure2
port: 8443
---
apiVersion: v1
kind: Service
metadata:
name: whoami-ipv6
namespace: default
spec:
ports:
- name: web
port: 8080
selector:
app: traefiklabs
task: whoami-ipv6
---
kind: Endpoints
apiVersion: v1
metadata:
name: whoami-ipv6
namespace: default
subsets:
- addresses:
- ip: "2001:db8:85a3:8d3:1319:8a2e:370:7348"
ports:
- name: web
port: 8080
---
apiVersion: v1
kind: Service
@ -157,5 +186,16 @@ spec:
protocol: TCP
port: 443
---
apiVersion: v1
kind: Service
metadata:
name: external-svc-with-ipv6
namespace: default
spec:
externalName: "2001:db8:85a3:8d3:1319:8a2e:370:7347"
type: ExternalName
ports:
- name: http
protocol: TCP
port: 8080

View file

@ -132,6 +132,36 @@ subsets:
- name: myapp4
port: 8084
---
apiVersion: v1
kind: Service
metadata:
name: whoamitcp-ipv6
namespace: default
spec:
ports:
- name: myapp-ipv6
port: 8080
selector:
app: traefiklabs
task: whoamitcp-ipv6
---
kind: Endpoints
apiVersion: v1
metadata:
name: whoamitcp-ipv6
namespace: default
subsets:
- addresses:
- ip: "fd00:10:244:0:1::3"
- ip: "2001:db8:85a3:8d3:1319:8a2e:370:7348"
ports:
- name: myapp-ipv6
port: 8080
---
apiVersion: v1
kind: Service
@ -167,4 +197,14 @@ spec:
type: ExternalName
ports:
- name: http
protocol: TCP
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: external.service.with.ipv6
namespace: default
spec:
externalName: "fe80::200:5aee:feaa:20a2"
type: ExternalName

View file

@ -0,0 +1,17 @@
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
name: test.route
namespace: default
spec:
entryPoints:
- foo
routes:
- match: HostSNI(`*`)
services:
- name: whoamitcp-ipv6
port: 8080
- name: external.service.with.ipv6
port: 8080

View file

@ -101,3 +101,32 @@ subsets:
ports:
- name: myapp4
port: 8084
---
apiVersion: v1
kind: Service
metadata:
name: whoamiudp-ipv6
namespace: default
spec:
ports:
- name: myapp-ipv6
port: 8080
selector:
app: traefiklabs
task: whoamiudp-ipv6
---
kind: Endpoints
apiVersion: v1
metadata:
name: whoamiudp-ipv6
namespace: default
subsets:
- addresses:
- ip: "fd00:10:244:0:1::3"
ports:
- name: myapp-ipv6
port: 8080

View file

@ -0,0 +1,14 @@
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteUDP
metadata:
name: test.route
namespace: default
spec:
entryPoints:
- foo
routes:
- services:
- name: whoamiudp-ipv6
port: 8080

View file

@ -0,0 +1,18 @@
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: test.route
namespace: default
spec:
entryPoints:
- foo
routes:
- match: Host(`foo.com`) && PathPrefix(`/bar`)
kind: Rule
services:
- name: whoami-ipv6
port: 8080
- name: external-svc-with-ipv6
port: 8080

View file

@ -4,6 +4,8 @@ import (
"context"
"errors"
"fmt"
"net"
"strconv"
"strings"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
@ -301,8 +303,10 @@ func (c configBuilder) loadServers(fallbackNamespace string, svc v1alpha1.LoadBa
return nil, err
}
hostPort := net.JoinHostPort(service.Spec.ExternalName, strconv.Itoa(int(svcPort.Port)))
return append(servers, dynamic.Server{
URL: fmt.Sprintf("%s://%s:%d", protocol, service.Spec.ExternalName, svcPort.Port),
URL: fmt.Sprintf("%s://%s", protocol, hostPort),
}), nil
}
@ -336,8 +340,10 @@ func (c configBuilder) loadServers(fallbackNamespace string, svc v1alpha1.LoadBa
}
for _, addr := range subset.Addresses {
hostPort := net.JoinHostPort(addr.IP, strconv.Itoa(int(port)))
servers = append(servers, dynamic.Server{
URL: fmt.Sprintf("%s://%s:%d", protocol, addr.IP, port),
URL: fmt.Sprintf("%s://%s", protocol, hostPort),
})
}
}

View file

@ -4,6 +4,8 @@ import (
"context"
"errors"
"fmt"
"net"
"strconv"
"strings"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
@ -165,7 +167,7 @@ func loadTCPServers(client Client, namespace string, svc v1alpha1.ServiceTCP) ([
var servers []dynamic.TCPServer
if service.Spec.Type == corev1.ServiceTypeExternalName {
servers = append(servers, dynamic.TCPServer{
Address: fmt.Sprintf("%s:%d", service.Spec.ExternalName, svcPort.Port),
Address: net.JoinHostPort(service.Spec.ExternalName, strconv.Itoa(int(svcPort.Port))),
})
} else {
endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, svc.Name)
@ -196,7 +198,7 @@ func loadTCPServers(client Client, namespace string, svc v1alpha1.ServiceTCP) ([
for _, addr := range subset.Addresses {
servers = append(servers, dynamic.TCPServer{
Address: fmt.Sprintf("%s:%d", addr.IP, port),
Address: net.JoinHostPort(addr.IP, strconv.Itoa(int(port))),
})
}
}

View file

@ -987,6 +987,128 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "Ingress Route with IPv6 backends",
paths: []string{
"services.yml", "with_ipv6.yml",
"tcp/services.yml", "tcp/with_ipv6.yml",
"udp/services.yml", "udp/with_ipv6.yml",
},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{
"default-test.route-0": {
EntryPoints: []string{"foo"},
Service: "default-test.route-0",
},
},
Services: map[string]*dynamic.UDPService{
"default-test.route-0": {
LoadBalancer: &dynamic.UDPServersLoadBalancer{
Servers: []dynamic.UDPServer{
{
Address: "[fd00:10:244:0:1::3]:8080",
},
},
},
},
},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{
"default-test.route-673acf455cb2dab0b43a": {
EntryPoints: []string{"foo"},
Service: "default-test.route-673acf455cb2dab0b43a",
Rule: "HostSNI(`*`)",
},
},
Services: map[string]*dynamic.TCPService{
"default-test.route-673acf455cb2dab0b43a": {
Weighted: &dynamic.TCPWeightedRoundRobin{
Services: []dynamic.TCPWRRService{
{
Name: "default-test.route-673acf455cb2dab0b43a-whoamitcp-ipv6-8080",
Weight: func(i int) *int { return &i }(1),
},
{
Name: "default-test.route-673acf455cb2dab0b43a-external.service.with.ipv6-8080",
Weight: func(i int) *int { return &i }(1),
},
},
},
},
"default-test.route-673acf455cb2dab0b43a-whoamitcp-ipv6-8080": {
LoadBalancer: &dynamic.TCPServersLoadBalancer{
Servers: []dynamic.TCPServer{
{
Address: "[fd00:10:244:0:1::3]:8080",
},
{
Address: "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:8080",
},
},
},
},
"default-test.route-673acf455cb2dab0b43a-external.service.with.ipv6-8080": {
LoadBalancer: &dynamic.TCPServersLoadBalancer{
Servers: []dynamic.TCPServer{
{
Address: "[fe80::200:5aee:feaa:20a2]:8080",
},
},
},
},
},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"default-test-route-6b204d94623b3df4370c": {
EntryPoints: []string{"foo"},
Service: "default-test-route-6b204d94623b3df4370c",
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"default-whoami-ipv6-8080": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]:8080",
},
},
PassHostHeader: func(i bool) *bool { return &i }(true),
},
},
"default-external-svc-with-ipv6-8080": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://[2001:db8:85a3:8d3:1319:8a2e:370:7347]:8080",
},
},
PassHostHeader: func(i bool) *bool { return &i }(true),
},
},
"default-test-route-6b204d94623b3df4370c": {
Weighted: &dynamic.WeightedRoundRobin{
Services: []dynamic.WRRService{
{
Name: "default-whoami-ipv6-8080",
Weight: func(i int) *int { return &i }(1),
},
{
Name: "default-external-svc-with-ipv6-8080",
Weight: func(i int) *int { return &i }(1),
},
},
},
},
},
},
TLS: &dynamic.TLSConfiguration{},
},
},
}
for _, test := range testCases {

View file

@ -4,6 +4,8 @@ import (
"context"
"errors"
"fmt"
"net"
"strconv"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
"github.com/traefik/traefik/v2/pkg/log"
@ -121,7 +123,7 @@ func loadUDPServers(client Client, namespace string, svc v1alpha1.ServiceUDP) ([
var servers []dynamic.UDPServer
if service.Spec.Type == corev1.ServiceTypeExternalName {
servers = append(servers, dynamic.UDPServer{
Address: fmt.Sprintf("%s:%d", service.Spec.ExternalName, portSpec.Port),
Address: net.JoinHostPort(service.Spec.ExternalName, strconv.Itoa(int(portSpec.Port))),
})
} else {
endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, svc.Name)
@ -152,7 +154,7 @@ func loadUDPServers(client Client, namespace string, svc v1alpha1.ServiceUDP) ([
for _, addr := range subset.Addresses {
servers = append(servers, dynamic.UDPServer{
Address: fmt.Sprintf("%s:%d", addr.IP, port),
Address: net.JoinHostPort(addr.IP, strconv.Itoa(int(port))),
})
}
}