Improve kubernetes external name service support
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
This commit is contained in:
parent
e511cfe2e4
commit
3b85dc9618
17 changed files with 876 additions and 48 deletions
|
@ -4,6 +4,8 @@ import (
|
|||
"context"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/containous/traefik/v2/pkg/provider"
|
||||
"github.com/containous/traefik/v2/pkg/tls"
|
||||
|
@ -906,6 +908,106 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Simple Ingress Route, with externalName service",
|
||||
paths: []string{"tcp/services.yml", "tcp/with_externalname.yml"},
|
||||
expected: &dynamic.Configuration{
|
||||
UDP: &dynamic.UDPConfiguration{
|
||||
Routers: map[string]*dynamic.UDPRouter{},
|
||||
Services: map[string]*dynamic.UDPService{},
|
||||
},
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{
|
||||
"default-test.route-fdd3e9338e47a45efefc": {
|
||||
EntryPoints: []string{"foo"},
|
||||
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||
Rule: "HostSNI(`foo.com`)",
|
||||
},
|
||||
},
|
||||
Services: map[string]*dynamic.TCPService{
|
||||
"default-test.route-fdd3e9338e47a45efefc": {
|
||||
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||
Servers: []dynamic.TCPServer{
|
||||
{
|
||||
Address: "external.domain:8000",
|
||||
Port: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{},
|
||||
},
|
||||
TLS: &dynamic.TLSConfiguration{},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Ingress Route, externalName service with port",
|
||||
paths: []string{"tcp/services.yml", "tcp/with_externalname_with_port.yml"},
|
||||
expected: &dynamic.Configuration{
|
||||
UDP: &dynamic.UDPConfiguration{
|
||||
Routers: map[string]*dynamic.UDPRouter{},
|
||||
Services: map[string]*dynamic.UDPService{},
|
||||
},
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{
|
||||
"default-test.route-fdd3e9338e47a45efefc": {
|
||||
EntryPoints: []string{"foo"},
|
||||
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||
Rule: "HostSNI(`foo.com`)",
|
||||
},
|
||||
},
|
||||
Services: map[string]*dynamic.TCPService{
|
||||
"default-test.route-fdd3e9338e47a45efefc": {
|
||||
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||
Servers: []dynamic.TCPServer{
|
||||
{
|
||||
Address: "external.domain:80",
|
||||
Port: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{},
|
||||
},
|
||||
TLS: &dynamic.TLSConfiguration{},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Ingress Route, externalName service without port",
|
||||
paths: []string{"tcp/services.yml", "tcp/with_externalname_without_ports.yml"},
|
||||
expected: &dynamic.Configuration{
|
||||
UDP: &dynamic.UDPConfiguration{
|
||||
Routers: map[string]*dynamic.UDPRouter{},
|
||||
Services: map[string]*dynamic.UDPService{},
|
||||
},
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{
|
||||
"default-test.route-fdd3e9338e47a45efefc": {
|
||||
EntryPoints: []string{"foo"},
|
||||
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||
Rule: "HostSNI(`foo.com`)",
|
||||
},
|
||||
},
|
||||
Services: map[string]*dynamic.TCPService{},
|
||||
},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{},
|
||||
},
|
||||
TLS: &dynamic.TLSConfiguration{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
|
@ -2860,6 +2962,134 @@ func TestLoadIngressRoutes(t *testing.T) {
|
|||
{
|
||||
desc: "port selected by name (TODO)",
|
||||
},
|
||||
{
|
||||
desc: "Simple Ingress Route, with externalName service",
|
||||
paths: []string{"services.yml", "with_externalname.yml"},
|
||||
expected: &dynamic.Configuration{
|
||||
UDP: &dynamic.UDPConfiguration{
|
||||
Routers: map[string]*dynamic.UDPRouter{},
|
||||
Services: map[string]*dynamic.UDPService{},
|
||||
},
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{},
|
||||
Services: map[string]*dynamic.TCPService{},
|
||||
},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"default-test-route-6f97418635c7e18853da": {
|
||||
EntryPoints: []string{"foo"},
|
||||
Service: "default-test-route-6f97418635c7e18853da",
|
||||
Rule: "Host(`foo.com`)",
|
||||
}},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{
|
||||
"default-test-route-6f97418635c7e18853da": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://external.domain:80",
|
||||
},
|
||||
},
|
||||
PassHostHeader: Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
TLS: &dynamic.TLSConfiguration{},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Ingress Route, externalName service with http",
|
||||
paths: []string{"services.yml", "with_externalname_with_http.yml"},
|
||||
expected: &dynamic.Configuration{
|
||||
UDP: &dynamic.UDPConfiguration{
|
||||
Routers: map[string]*dynamic.UDPRouter{},
|
||||
Services: map[string]*dynamic.UDPService{},
|
||||
},
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{},
|
||||
Services: map[string]*dynamic.TCPService{},
|
||||
},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"default-test-route-6f97418635c7e18853da": {
|
||||
EntryPoints: []string{"foo"},
|
||||
Service: "default-test-route-6f97418635c7e18853da",
|
||||
Rule: "Host(`foo.com`)",
|
||||
}},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{
|
||||
"default-test-route-6f97418635c7e18853da": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://external.domain:80",
|
||||
},
|
||||
},
|
||||
PassHostHeader: Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
TLS: &dynamic.TLSConfiguration{},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Ingress Route, externalName service with https",
|
||||
paths: []string{"services.yml", "with_externalname_with_https.yml"},
|
||||
expected: &dynamic.Configuration{
|
||||
UDP: &dynamic.UDPConfiguration{
|
||||
Routers: map[string]*dynamic.UDPRouter{},
|
||||
Services: map[string]*dynamic.UDPService{},
|
||||
},
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{},
|
||||
Services: map[string]*dynamic.TCPService{},
|
||||
},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"default-test-route-6f97418635c7e18853da": {
|
||||
EntryPoints: []string{"foo"},
|
||||
Service: "default-test-route-6f97418635c7e18853da",
|
||||
Rule: "Host(`foo.com`)",
|
||||
}},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{
|
||||
"default-test-route-6f97418635c7e18853da": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "https://external.domain:443",
|
||||
},
|
||||
},
|
||||
PassHostHeader: Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
TLS: &dynamic.TLSConfiguration{},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Ingress Route, externalName service without ports",
|
||||
paths: []string{"services.yml", "with_externalname_without_ports.yml"},
|
||||
expected: &dynamic.Configuration{
|
||||
UDP: &dynamic.UDPConfiguration{
|
||||
Routers: map[string]*dynamic.UDPRouter{},
|
||||
Services: map[string]*dynamic.UDPService{},
|
||||
},
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{},
|
||||
Services: map[string]*dynamic.TCPService{},
|
||||
},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{},
|
||||
},
|
||||
TLS: &dynamic.TLSConfiguration{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
|
@ -3255,3 +3485,148 @@ func TestParseServiceProtocol(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetServicePort(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
svc *corev1.Service
|
||||
port int32
|
||||
expected *corev1.ServicePort
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
desc: "Basic",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
desc: "Matching ports, with no service type",
|
||||
svc: &corev1.Service{
|
||||
Spec: corev1.ServiceSpec{
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
port: 80,
|
||||
expected: &corev1.ServicePort{
|
||||
Port: 80,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Matching ports 0",
|
||||
svc: &corev1.Service{
|
||||
Spec: corev1.ServiceSpec{
|
||||
Ports: []corev1.ServicePort{
|
||||
{},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
desc: "Matching ports 0 (with external name)",
|
||||
svc: &corev1.Service{
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeExternalName,
|
||||
Ports: []corev1.ServicePort{
|
||||
{},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
desc: "Mismatching, only port(Ingress) defined",
|
||||
svc: &corev1.Service{
|
||||
Spec: corev1.ServiceSpec{},
|
||||
},
|
||||
port: 80,
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
desc: "Mismatching, only port(Ingress) defined with external name",
|
||||
svc: &corev1.Service{
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeExternalName,
|
||||
},
|
||||
},
|
||||
port: 80,
|
||||
expected: &corev1.ServicePort{
|
||||
Port: 80,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Mismatching, only Service port defined",
|
||||
svc: &corev1.Service{
|
||||
Spec: corev1.ServiceSpec{
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
desc: "Mismatching, only Service port defined with external name",
|
||||
svc: &corev1.Service{
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeExternalName,
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
desc: "Two different ports defined",
|
||||
svc: &corev1.Service{
|
||||
Spec: corev1.ServiceSpec{
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
port: 443,
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
desc: "Two different ports defined (with external name)",
|
||||
svc: &corev1.Service{
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeExternalName,
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
port: 443,
|
||||
expected: &corev1.ServicePort{
|
||||
Port: 443,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
actual, err := getServicePort(test.svc, test.port)
|
||||
if test.expectError {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.Equal(t, test.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue