Add named port support to Kubernetes IngressRoute CRDs
This commit is contained in:
parent
b1ddd0e038
commit
bbee63fcf3
10 changed files with 154 additions and 57 deletions
|
@ -145,7 +145,7 @@ The Kubernetes Ingress Controller, The Custom Resource Way.
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
entryPoints:
|
entryPoints:
|
||||||
- fooudp
|
- udpep
|
||||||
routes:
|
routes:
|
||||||
- kind: Rule
|
- kind: Rule
|
||||||
services:
|
services:
|
||||||
|
@ -331,7 +331,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
|
||||||
name: foo
|
name: foo
|
||||||
namespace: default
|
namespace: default
|
||||||
passHostHeader: true
|
passHostHeader: true
|
||||||
port: 80
|
port: 80 # [9]
|
||||||
responseForwarding:
|
responseForwarding:
|
||||||
flushInterval: 1ms
|
flushInterval: 1ms
|
||||||
scheme: https
|
scheme: https
|
||||||
|
@ -343,21 +343,21 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
|
||||||
sameSite: none
|
sameSite: none
|
||||||
strategy: RoundRobin
|
strategy: RoundRobin
|
||||||
weight: 10
|
weight: 10
|
||||||
tls: # [9]
|
tls: # [10]
|
||||||
secretName: supersecret # [10]
|
secretName: supersecret # [11]
|
||||||
options: # [11]
|
options: # [12]
|
||||||
name: opt # [12]
|
name: opt # [13]
|
||||||
namespace: default # [13]
|
namespace: default # [14]
|
||||||
certResolver: foo # [14]
|
certResolver: foo # [15]
|
||||||
domains: # [15]
|
domains: # [16]
|
||||||
- main: example.net # [16]
|
- main: example.net # [17]
|
||||||
sans: # [17]
|
sans: # [18]
|
||||||
- a.example.net
|
- a.example.net
|
||||||
- b.example.net
|
- b.example.net
|
||||||
```
|
```
|
||||||
|
|
||||||
| Ref | Attribute | Purpose |
|
| Ref | Attribute | Purpose |
|
||||||
|------|----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------|------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| [1] | `entryPoints` | List of [entry points](../routers/index.md#entrypoints) names |
|
| [1] | `entryPoints` | List of [entry points](../routers/index.md#entrypoints) names |
|
||||||
| [2] | `routes` | List of routes |
|
| [2] | `routes` | List of routes |
|
||||||
| [3] | `routes[n].match` | Defines the [rule](../routers/index.md#rule) corresponding to an underlying router. |
|
| [3] | `routes[n].match` | Defines the [rule](../routers/index.md#rule) corresponding to an underlying router. |
|
||||||
|
@ -366,15 +366,16 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
|
||||||
| [6] | `middlewares[n].name` | Defines the [Middleware](#kind-middleware) name |
|
| [6] | `middlewares[n].name` | Defines the [Middleware](#kind-middleware) name |
|
||||||
| [7] | `middlewares[n].namespace` | Defines the [Middleware](#kind-middleware) namespace |
|
| [7] | `middlewares[n].namespace` | Defines the [Middleware](#kind-middleware) namespace |
|
||||||
| [8] | `routes[n].services` | List of any combination of [TraefikService](#kind-traefikservice) and reference to a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) (See below for `ExternalName Service` setup) |
|
| [8] | `routes[n].services` | List of any combination of [TraefikService](#kind-traefikservice) and reference to a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) (See below for `ExternalName Service` setup) |
|
||||||
| [9] | `tls` | Defines [TLS](../routers/index.md#tls) certificate configuration |
|
| [9] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/). This can be a reference to a named port. |
|
||||||
| [10] | `tls.secretName` | Defines the [secret](https://kubernetes.io/docs/concepts/configuration/secret/) name used to store the certificate (in the `IngressRoute` namespace) |
|
| [10] | `tls` | Defines [TLS](../routers/index.md#tls) certificate configuration |
|
||||||
| [11] | `tls.options` | Defines the reference to a [TLSOption](#kind-tlsoption) |
|
| [11] | `tls.secretName` | Defines the [secret](https://kubernetes.io/docs/concepts/configuration/secret/) name used to store the certificate (in the `IngressRoute` namespace) |
|
||||||
| [12] | `options.name` | Defines the [TLSOption](#kind-tlsoption) name |
|
| [12] | `tls.options` | Defines the reference to a [TLSOption](#kind-tlsoption) |
|
||||||
| [13] | `options.namespace` | Defines the [TLSOption](#kind-tlsoption) namespace |
|
| [13] | `options.name` | Defines the [TLSOption](#kind-tlsoption) name |
|
||||||
| [14] | `tls.certResolver` | Defines the reference to a [CertResolver](../routers/index.md#certresolver) |
|
| [14] | `options.namespace` | Defines the [TLSOption](#kind-tlsoption) namespace |
|
||||||
| [15] | `tls.domains` | List of [domains](../routers/index.md#domains) |
|
| [15] | `tls.certResolver` | Defines the reference to a [CertResolver](../routers/index.md#certresolver) |
|
||||||
| [16] | `domains[n].main` | Defines the main domain name |
|
| [16] | `tls.domains` | List of [domains](../routers/index.md#domains) |
|
||||||
| [17] | `domains[n].sans` | List of SANs (alternative domains) |
|
| [17] | `domains[n].main` | Defines the main domain name |
|
||||||
|
| [18] | `domains[n].sans` | List of SANs (alternative domains) |
|
||||||
|
|
||||||
??? example "Declaring an IngressRoute"
|
??? example "Declaring an IngressRoute"
|
||||||
|
|
||||||
|
@ -1113,7 +1114,7 @@ Register the `IngressRouteTCP` [kind](../../reference/dynamic-configuration/kube
|
||||||
| [3] | `routes[n].match` | Defines the [rule](../routers/index.md#rule_1) corresponding to an underlying router |
|
| [3] | `routes[n].match` | Defines the [rule](../routers/index.md#rule_1) corresponding to an underlying router |
|
||||||
| [4] | `routes[n].services` | List of [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) definitions (See below for `ExternalName Service` setup) |
|
| [4] | `routes[n].services` | List of [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) definitions (See below for `ExternalName Service` setup) |
|
||||||
| [5] | `services[n].name` | Defines the name of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) |
|
| [5] | `services[n].name` | Defines the name of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) |
|
||||||
| [6] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) |
|
| [6] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/). This can be a reference to a named port. |
|
||||||
| [7] | `services[n].weight` | Defines the weight to apply to the server load balancing |
|
| [7] | `services[n].weight` | Defines the weight to apply to the server load balancing |
|
||||||
| [8] | `services[n].terminationDelay` | corresponds to the deadline that the proxy sets, after one of its connected peers indicates it has closed the writing capability of its connection, to close the reading capability as well, hence fully terminating the connection. It is a duration in milliseconds, defaulting to 100. A negative value means an infinite deadline (i.e. the reading capability is never closed). |
|
| [8] | `services[n].terminationDelay` | corresponds to the deadline that the proxy sets, after one of its connected peers indicates it has closed the writing capability of its connection, to close the reading capability as well, hence fully terminating the connection. It is a duration in milliseconds, defaulting to 100. A negative value means an infinite deadline (i.e. the reading capability is never closed). |
|
||||||
| [9] | `proxyProtocol` | Defines the [PROXY protocol](../services/index.md#proxy-protocol) configuration |
|
| [9] | `proxyProtocol` | Defines the [PROXY protocol](../services/index.md#proxy-protocol) configuration |
|
||||||
|
@ -1323,7 +1324,7 @@ Register the `IngressRouteUDP` [kind](../../reference/dynamic-configuration/kube
|
||||||
| [2] | `routes` | List of routes |
|
| [2] | `routes` | List of routes |
|
||||||
| [3] | `routes[n].services` | List of [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) definitions |
|
| [3] | `routes[n].services` | List of [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) definitions |
|
||||||
| [4] | `services[n].name` | Defines the name of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) |
|
| [4] | `services[n].name` | Defines the name of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) |
|
||||||
| [6] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) |
|
| [6] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/). This can be a reference to a named port. |
|
||||||
| [7] | `services[n].weight` | Defines the weight to apply to the server load balancing |
|
| [7] | `services[n].weight` | Defines the weight to apply to the server load balancing |
|
||||||
|
|
||||||
??? example "Declaring an IngressRouteUDP"
|
??? example "Declaring an IngressRouteUDP"
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/traefik/traefik/v2/pkg/tls"
|
"github.com/traefik/traefik/v2/pkg/tls"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -323,18 +324,18 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
|
||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
|
|
||||||
func getServicePort(svc *corev1.Service, port int32) (*corev1.ServicePort, error) {
|
func getServicePort(svc *corev1.Service, port intstr.IntOrString) (*corev1.ServicePort, error) {
|
||||||
if svc == nil {
|
if svc == nil {
|
||||||
return nil, errors.New("service is not defined")
|
return nil, errors.New("service is not defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
if port == 0 {
|
if (port.Type == intstr.Int && port.IntVal == 0) || (port.Type == intstr.String && port.StrVal == "") {
|
||||||
return nil, errors.New("ingressRoute service port not defined")
|
return nil, errors.New("ingressRoute service port not defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
hasValidPort := false
|
hasValidPort := false
|
||||||
for _, p := range svc.Spec.Ports {
|
for _, p := range svc.Spec.Ports {
|
||||||
if p.Port == port {
|
if (port.Type == intstr.Int && port.IntVal == p.Port) || (port.Type == intstr.String && port.StrVal == p.Name) {
|
||||||
return &p, nil
|
return &p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,8 +344,8 @@ func getServicePort(svc *corev1.Service, port int32) (*corev1.ServicePort, error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if svc.Spec.Type != corev1.ServiceTypeExternalName {
|
if svc.Spec.Type != corev1.ServiceTypeExternalName || port.Type == intstr.String {
|
||||||
return nil, fmt.Errorf("service port not found: %d", port)
|
return nil, fmt.Errorf("service port not found: %s", &port)
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasValidPort {
|
if hasValidPort {
|
||||||
|
@ -352,7 +353,7 @@ func getServicePort(svc *corev1.Service, port int32) (*corev1.ServicePort, error
|
||||||
Warning("The port %d from IngressRoute doesn't match with ports defined in the ExternalName service %s/%s.", port, svc.Namespace, svc.Name)
|
Warning("The port %d from IngressRoute doesn't match with ports defined in the ExternalName service %s/%s.", port, svc.Namespace, svc.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &corev1.ServicePort{Port: port}, nil
|
return &corev1.ServicePort{Port: port.IntVal}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) createErrorPageMiddleware(client Client, namespace string, errorPage *v1alpha1.ErrorPage) (*dynamic.ErrorPage, *dynamic.Service, error) {
|
func (p *Provider) createErrorPageMiddleware(client Client, namespace string, errorPage *v1alpha1.ErrorPage) (*dynamic.ErrorPage, *dynamic.Service, error) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1"
|
"github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1"
|
||||||
"github.com/traefik/traefik/v2/pkg/tls"
|
"github.com/traefik/traefik/v2/pkg/tls"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -399,7 +400,7 @@ func (c configBuilder) nameAndService(ctx context.Context, parentNamespace strin
|
||||||
|
|
||||||
return fullName, serversLB, nil
|
return fullName, serversLB, nil
|
||||||
case service.Kind == "TraefikService":
|
case service.Kind == "TraefikService":
|
||||||
return fullServiceName(svcCtx, namespace, service, 0), nil, nil
|
return fullServiceName(svcCtx, namespace, service, intstr.FromInt(0)), nil, nil
|
||||||
default:
|
default:
|
||||||
return "", nil, fmt.Errorf("unsupported service kind %s", service.Kind)
|
return "", nil, fmt.Errorf("unsupported service kind %s", service.Kind)
|
||||||
}
|
}
|
||||||
|
@ -414,9 +415,9 @@ func splitSvcNameProvider(name string) (string, string) {
|
||||||
return svc, pvd
|
return svc, pvd
|
||||||
}
|
}
|
||||||
|
|
||||||
func fullServiceName(ctx context.Context, namespace string, service v1alpha1.LoadBalancerSpec, port int32) string {
|
func fullServiceName(ctx context.Context, namespace string, service v1alpha1.LoadBalancerSpec, port intstr.IntOrString) string {
|
||||||
if port != 0 {
|
if (port.Type == intstr.Int && port.IntVal != 0) || (port.Type == intstr.String && port.StrVal != "") {
|
||||||
return provider.Normalize(fmt.Sprintf("%s-%s-%d", namespace, service.Name, port))
|
return provider.Normalize(fmt.Sprintf("%s-%s-%s", namespace, service.Name, &port))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(service.Name, providerNamespaceSeparator) {
|
if !strings.Contains(service.Name, providerNamespaceSeparator) {
|
||||||
|
|
|
@ -71,7 +71,7 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceKey := fmt.Sprintf("%s-%s-%d", serviceName, service.Name, service.Port)
|
serviceKey := fmt.Sprintf("%s-%s-%s", serviceName, service.Name, &service.Port)
|
||||||
conf.Services[serviceKey] = balancerServerTCP
|
conf.Services[serviceKey] = balancerServerTCP
|
||||||
|
|
||||||
srv := dynamic.TCPWRRService{Name: serviceKey}
|
srv := dynamic.TCPWRRService{Name: serviceKey}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/traefik/traefik/v2/pkg/tls"
|
"github.com/traefik/traefik/v2/pkg/tls"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
kubefake "k8s.io/client-go/kubernetes/fake"
|
kubefake "k8s.io/client-go/kubernetes/fake"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -3738,7 +3739,7 @@ func TestGetServicePort(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
svc *corev1.Service
|
svc *corev1.Service
|
||||||
port int32
|
port intstr.IntOrString
|
||||||
expected *corev1.ServicePort
|
expected *corev1.ServicePort
|
||||||
expectError bool
|
expectError bool
|
||||||
}{
|
}{
|
||||||
|
@ -3757,7 +3758,7 @@ func TestGetServicePort(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
port: 80,
|
port: intstr.FromInt(80),
|
||||||
expected: &corev1.ServicePort{
|
expected: &corev1.ServicePort{
|
||||||
Port: 80,
|
Port: 80,
|
||||||
},
|
},
|
||||||
|
@ -3785,12 +3786,57 @@ func TestGetServicePort(t *testing.T) {
|
||||||
},
|
},
|
||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Matching named port",
|
||||||
|
svc: &corev1.Service{
|
||||||
|
Spec: corev1.ServiceSpec{
|
||||||
|
Ports: []corev1.ServicePort{
|
||||||
|
{
|
||||||
|
Name: "http",
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
port: intstr.FromString("http"),
|
||||||
|
expected: &corev1.ServicePort{
|
||||||
|
Name: "http",
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Matching named port (with external name)",
|
||||||
|
svc: &corev1.Service{
|
||||||
|
Spec: corev1.ServiceSpec{
|
||||||
|
Type: corev1.ServiceTypeExternalName,
|
||||||
|
Ports: []corev1.ServicePort{
|
||||||
|
{
|
||||||
|
Name: "http",
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
port: intstr.FromString("http"),
|
||||||
|
expected: &corev1.ServicePort{
|
||||||
|
Name: "http",
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "Mismatching, only port(Ingress) defined",
|
desc: "Mismatching, only port(Ingress) defined",
|
||||||
svc: &corev1.Service{
|
svc: &corev1.Service{
|
||||||
Spec: corev1.ServiceSpec{},
|
Spec: corev1.ServiceSpec{},
|
||||||
},
|
},
|
||||||
port: 80,
|
port: intstr.FromInt(80),
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Mismatching, only named port(Ingress) defined",
|
||||||
|
svc: &corev1.Service{
|
||||||
|
Spec: corev1.ServiceSpec{},
|
||||||
|
},
|
||||||
|
port: intstr.FromString("http"),
|
||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -3800,11 +3846,21 @@ func TestGetServicePort(t *testing.T) {
|
||||||
Type: corev1.ServiceTypeExternalName,
|
Type: corev1.ServiceTypeExternalName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
port: 80,
|
port: intstr.FromInt(80),
|
||||||
expected: &corev1.ServicePort{
|
expected: &corev1.ServicePort{
|
||||||
Port: 80,
|
Port: 80,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Mismatching, only named port(Ingress) defined with external name",
|
||||||
|
svc: &corev1.Service{
|
||||||
|
Spec: corev1.ServiceSpec{
|
||||||
|
Type: corev1.ServiceTypeExternalName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
port: intstr.FromString("http"),
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "Mismatching, only Service port defined",
|
desc: "Mismatching, only Service port defined",
|
||||||
svc: &corev1.Service{
|
svc: &corev1.Service{
|
||||||
|
@ -3843,7 +3899,22 @@ func TestGetServicePort(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
port: 443,
|
port: intstr.FromInt(443),
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Two different named ports defined",
|
||||||
|
svc: &corev1.Service{
|
||||||
|
Spec: corev1.ServiceSpec{
|
||||||
|
Ports: []corev1.ServicePort{
|
||||||
|
{
|
||||||
|
Name: "foo",
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
port: intstr.FromString("bar"),
|
||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -3858,11 +3929,27 @@ func TestGetServicePort(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
port: 443,
|
port: intstr.FromInt(443),
|
||||||
expected: &corev1.ServicePort{
|
expected: &corev1.ServicePort{
|
||||||
Port: 443,
|
Port: 443,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Two different named ports defined (with external name)",
|
||||||
|
svc: &corev1.Service{
|
||||||
|
Spec: corev1.ServiceSpec{
|
||||||
|
Type: corev1.ServiceTypeExternalName,
|
||||||
|
Ports: []corev1.ServicePort{
|
||||||
|
{
|
||||||
|
Name: "foo",
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
port: intstr.FromString("bar"),
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
test := test
|
test := test
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/traefik/traefik/v2/pkg/log"
|
"github.com/traefik/traefik/v2/pkg/log"
|
||||||
"github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1"
|
"github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) loadIngressRouteUDPConfiguration(ctx context.Context, client Client) *dynamic.UDPConfiguration {
|
func (p *Provider) loadIngressRouteUDPConfiguration(ctx context.Context, client Client) *dynamic.UDPConfiguration {
|
||||||
|
@ -52,7 +53,7 @@ func (p *Provider) loadIngressRouteUDPConfiguration(ctx context.Context, client
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceKey := fmt.Sprintf("%s-%s-%d", serviceName, service.Name, service.Port)
|
serviceKey := fmt.Sprintf("%s-%s-%s", serviceName, service.Name, &service.Port)
|
||||||
conf.Services[serviceKey] = balancerServerUDP
|
conf.Services[serviceKey] = balancerServerUDP
|
||||||
|
|
||||||
srv := dynamic.UDPWRRService{Name: serviceKey}
|
srv := dynamic.UDPWRRService{Name: serviceKey}
|
||||||
|
@ -114,7 +115,7 @@ func loadUDPServers(client Client, namespace string, svc v1alpha1.ServiceUDP) ([
|
||||||
var portSpec *corev1.ServicePort
|
var portSpec *corev1.ServicePort
|
||||||
for _, p := range service.Spec.Ports {
|
for _, p := range service.Spec.Ports {
|
||||||
p := p
|
p := p
|
||||||
if svc.Port == p.Port {
|
if (svc.Port.Type == intstr.Int && svc.Port.IntVal == p.Port) || (svc.Port.Type == intstr.String && svc.Port.StrVal == p.Name) {
|
||||||
portSpec = &p
|
portSpec = &p
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/traefik/traefik/v2/pkg/types"
|
"github.com/traefik/traefik/v2/pkg/types"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IngressRouteSpec is a specification for a IngressRouteSpec resource.
|
// IngressRouteSpec is a specification for a IngressRouteSpec resource.
|
||||||
|
@ -67,7 +68,7 @@ type LoadBalancerSpec struct {
|
||||||
|
|
||||||
// Port and all the fields below are related to a servers load-balancer,
|
// Port and all the fields below are related to a servers load-balancer,
|
||||||
// and therefore should only be specified when Name references a Kubernetes Service.
|
// and therefore should only be specified when Name references a Kubernetes Service.
|
||||||
Port int32 `json:"port"`
|
Port intstr.IntOrString `json:"port"`
|
||||||
Scheme string `json:"scheme,omitempty"`
|
Scheme string `json:"scheme,omitempty"`
|
||||||
Strategy string `json:"strategy,omitempty"`
|
Strategy string `json:"strategy,omitempty"`
|
||||||
PassHostHeader *bool `json:"passHostHeader,omitempty"`
|
PassHostHeader *bool `json:"passHostHeader,omitempty"`
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/traefik/traefik/v2/pkg/types"
|
"github.com/traefik/traefik/v2/pkg/types"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IngressRouteTCPSpec is a specification for a IngressRouteTCPSpec resource.
|
// IngressRouteTCPSpec is a specification for a IngressRouteTCPSpec resource.
|
||||||
|
@ -56,7 +57,7 @@ type TLSStoreTCPRef struct {
|
||||||
type ServiceTCP struct {
|
type ServiceTCP struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Namespace string `json:"namespace"`
|
Namespace string `json:"namespace"`
|
||||||
Port int32 `json:"port"`
|
Port intstr.IntOrString `json:"port"`
|
||||||
Weight *int `json:"weight,omitempty"`
|
Weight *int `json:"weight,omitempty"`
|
||||||
TerminationDelay *int `json:"terminationDelay,omitempty"`
|
TerminationDelay *int `json:"terminationDelay,omitempty"`
|
||||||
ProxyProtocol *dynamic.ProxyProtocol `json:"proxyProtocol,omitempty"`
|
ProxyProtocol *dynamic.ProxyProtocol `json:"proxyProtocol,omitempty"`
|
||||||
|
|
|
@ -2,6 +2,7 @@ package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IngressRouteUDPSpec is a specification for a IngressRouteUDPSpec resource.
|
// IngressRouteUDPSpec is a specification for a IngressRouteUDPSpec resource.
|
||||||
|
@ -25,7 +26,7 @@ type TLSOptionUDPRef struct {
|
||||||
type ServiceUDP struct {
|
type ServiceUDP struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Namespace string `json:"namespace"`
|
Namespace string `json:"namespace"`
|
||||||
Port int32 `json:"port"`
|
Port intstr.IntOrString `json:"port"`
|
||||||
Weight *int `json:"weight,omitempty"`
|
Weight *int `json:"weight,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -507,6 +507,7 @@ func (in *LoadBalancerSpec) DeepCopyInto(out *LoadBalancerSpec) {
|
||||||
*out = new(dynamic.Sticky)
|
*out = new(dynamic.Sticky)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
|
out.Port = in.Port
|
||||||
if in.PassHostHeader != nil {
|
if in.PassHostHeader != nil {
|
||||||
in, out := &in.PassHostHeader, &out.PassHostHeader
|
in, out := &in.PassHostHeader, &out.PassHostHeader
|
||||||
*out = new(bool)
|
*out = new(bool)
|
||||||
|
@ -1001,6 +1002,7 @@ func (in *ServiceSpec) DeepCopy() *ServiceSpec {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ServiceTCP) DeepCopyInto(out *ServiceTCP) {
|
func (in *ServiceTCP) DeepCopyInto(out *ServiceTCP) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
out.Port = in.Port
|
||||||
if in.Weight != nil {
|
if in.Weight != nil {
|
||||||
in, out := &in.Weight, &out.Weight
|
in, out := &in.Weight, &out.Weight
|
||||||
*out = new(int)
|
*out = new(int)
|
||||||
|
@ -1032,6 +1034,7 @@ func (in *ServiceTCP) DeepCopy() *ServiceTCP {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ServiceUDP) DeepCopyInto(out *ServiceUDP) {
|
func (in *ServiceUDP) DeepCopyInto(out *ServiceUDP) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
out.Port = in.Port
|
||||||
if in.Weight != nil {
|
if in.Weight != nil {
|
||||||
in, out := &in.Weight, &out.Weight
|
in, out := &in.Weight, &out.Weight
|
||||||
*out = new(int)
|
*out = new(int)
|
||||||
|
|
Loading…
Reference in a new issue