Merge branch v2.8 into v2.9

This commit is contained in:
Fernandez Ludovic 2022-09-23 09:07:13 +02:00
commit c4cc30ccc6
9 changed files with 269 additions and 182 deletions

View file

@ -169,6 +169,70 @@ providers:
# ... # ...
``` ```
### `constraints`
_Optional, Default=""_
The `constraints` option can be set to an expression that Traefik matches against the container labels (task),
to determine whether to create any route for that container.
If none of the container labels match the expression, no route for that container is created.
If the expression is empty, all detected containers are included.
The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions,
as well as the usual boolean logic, as shown in examples below.
??? example "Constraints Expression Examples"
```toml
# Includes only containers having a label with key `a.label.name` and value `foo`
constraints = "Label(`a.label.name`, `foo`)"
```
```toml
# Excludes containers having any label with key `a.label.name` and value `foo`
constraints = "!Label(`a.label.name`, `value`)"
```
```toml
# With logical AND.
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
```
```toml
# With logical OR.
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
```
```toml
# With logical AND and OR, with precedence set by parentheses.
constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
```
```toml
# Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression.
constraints = "LabelRegex(`a.label.name`, `a.+`)"
```
For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).
```yaml tab="File (YAML)"
providers:
ecs:
constraints: "Label(`a.label.name`,`foo`)"
# ...
```
```toml tab="File (TOML)"
[providers.ecs]
constraints = "Label(`a.label.name`,`foo`)"
# ...
```
```bash tab="CLI"
--providers.ecs.constraints=Label(`a.label.name`,`foo`)
# ...
```
### `defaultRule` ### `defaultRule`
_Optional, Default=```Host(`{{ normalize .Name }}`)```_ _Optional, Default=```Host(`{{ normalize .Name }}`)```_

View file

@ -213,6 +213,7 @@ you can do so in two different ways:
List of providers that support these features: List of providers that support these features:
- [Docker](./docker.md#exposedbydefault) - [Docker](./docker.md#exposedbydefault)
- [ECS](./ecs.md#exposedbydefault)
- [Consul Catalog](./consul-catalog.md#exposedbydefault) - [Consul Catalog](./consul-catalog.md#exposedbydefault)
- [Nomad](./nomad.md#exposedbydefault) - [Nomad](./nomad.md#exposedbydefault)
- [Rancher](./rancher.md#exposedbydefault) - [Rancher](./rancher.md#exposedbydefault)
@ -223,6 +224,7 @@ List of providers that support these features:
List of providers that support constraints: List of providers that support constraints:
- [Docker](./docker.md#constraints) - [Docker](./docker.md#constraints)
- [ECS](./ecs.md#constraints)
- [Consul Catalog](./consul-catalog.md#constraints) - [Consul Catalog](./consul-catalog.md#constraints)
- [Nomad](./nomad.md#constraints) - [Nomad](./nomad.md#constraints)
- [Rancher](./rancher.md#constraints) - [Rancher](./rancher.md#constraints)

View file

@ -195,29 +195,27 @@ func (p *Provider) addServerTCP(item itemData, loadBalancer *dynamic.TCPServersL
return errors.New("load-balancer is not defined") return errors.New("load-balancer is not defined")
} }
var port string
if len(loadBalancer.Servers) > 0 {
port = loadBalancer.Servers[0].Port
}
if len(loadBalancer.Servers) == 0 { if len(loadBalancer.Servers) == 0 {
loadBalancer.Servers = []dynamic.TCPServer{{}} loadBalancer.Servers = []dynamic.TCPServer{{}}
} }
if item.Port != "" && port == "" {
port = item.Port
}
loadBalancer.Servers[0].Port = ""
if port == "" {
return errors.New("port is missing")
}
if item.Address == "" { if item.Address == "" {
return errors.New("address is missing") return errors.New("address is missing")
} }
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if port == "" {
port = item.Port
}
if port == "" {
return errors.New("port is missing")
}
loadBalancer.Servers[0].Address = net.JoinHostPort(item.Address, port) loadBalancer.Servers[0].Address = net.JoinHostPort(item.Address, port)
return nil return nil
} }
@ -230,21 +228,23 @@ func (p *Provider) addServerUDP(item itemData, loadBalancer *dynamic.UDPServersL
loadBalancer.Servers = []dynamic.UDPServer{{}} loadBalancer.Servers = []dynamic.UDPServer{{}}
} }
var port string if item.Address == "" {
if item.Port != "" { return errors.New("address is missing")
}
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if port == "" {
port = item.Port port = item.Port
loadBalancer.Servers[0].Port = ""
} }
if port == "" { if port == "" {
return errors.New("port is missing") return errors.New("port is missing")
} }
if item.Address == "" {
return errors.New("address is missing")
}
loadBalancer.Servers[0].Address = net.JoinHostPort(item.Address, port) loadBalancer.Servers[0].Address = net.JoinHostPort(item.Address, port)
return nil return nil
} }
@ -253,11 +253,6 @@ func (p *Provider) addServer(item itemData, loadBalancer *dynamic.ServersLoadBal
return errors.New("load-balancer is not defined") return errors.New("load-balancer is not defined")
} }
var port string
if len(loadBalancer.Servers) > 0 {
port = loadBalancer.Servers[0].Port
}
if len(loadBalancer.Servers) == 0 { if len(loadBalancer.Servers) == 0 {
server := dynamic.Server{} server := dynamic.Server{}
server.SetDefaults() server.SetDefaults()
@ -265,17 +260,19 @@ func (p *Provider) addServer(item itemData, loadBalancer *dynamic.ServersLoadBal
loadBalancer.Servers = []dynamic.Server{server} loadBalancer.Servers = []dynamic.Server{server}
} }
if item.Port != "" && port == "" { if item.Address == "" {
port = item.Port return errors.New("address is missing")
} }
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = "" loadBalancer.Servers[0].Port = ""
if port == "" { if port == "" {
return errors.New("port is missing") port = item.Port
} }
if item.Address == "" { if port == "" {
return errors.New("address is missing") return errors.New("port is missing")
} }
scheme := loadBalancer.Servers[0].Scheme scheme := loadBalancer.Servers[0].Scheme

View file

@ -2220,7 +2220,7 @@ func Test_buildConfiguration(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"traefik.tcp.routers.foo.rule": "HostSNI(`foo.bar`)", "traefik.tcp.routers.foo.rule": "HostSNI(`foo.bar`)",
"traefik.tcp.routers.foo.tls.options": "foo", "traefik.tcp.routers.foo.tls.options": "foo",
"traefik.tcp.services.foo.loadbalancer.server.port": "80", "traefik.tcp.services.foo.loadbalancer.server.port": "8080",
}, },
Address: "127.0.0.1", Address: "127.0.0.1",
Port: "80", Port: "80",
@ -2244,7 +2244,7 @@ func Test_buildConfiguration(t *testing.T) {
LoadBalancer: &dynamic.TCPServersLoadBalancer{ LoadBalancer: &dynamic.TCPServersLoadBalancer{
Servers: []dynamic.TCPServer{ Servers: []dynamic.TCPServer{
{ {
Address: "127.0.0.1:80", Address: "127.0.0.1:8080",
}, },
}, },
TerminationDelay: Int(100), TerminationDelay: Int(100),
@ -2858,6 +2858,57 @@ func Test_buildConfiguration(t *testing.T) {
}, },
}, },
}, },
{
desc: "UDP service with labels only",
ConnectAware: true,
items: []itemData{
{
ID: "1",
Node: "Node1",
Datacenter: "dc1",
Name: "Test",
Namespace: "ns",
Labels: map[string]string{
"traefik.udp.routers.test-udp-label.service": "test-udp-label-service",
"traefik.udp.routers.test-udp-label.entryPoints": "udp",
"traefik.udp.services.test-udp-label-service.loadBalancer.server.port": "21116",
},
Address: "127.0.0.1",
Port: "80",
Status: api.HealthPassing,
},
},
expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{
"test-udp-label": {
EntryPoints: []string{"udp"},
Service: "test-udp-label-service",
},
},
Services: map[string]*dynamic.UDPService{
"test-udp-label-service": {
LoadBalancer: &dynamic.UDPServersLoadBalancer{
Servers: []dynamic.UDPServer{
{Address: "127.0.0.1:21116"},
},
},
},
},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
},
},
} }
for _, test := range testCases { for _, test := range testCases {

View file

@ -196,28 +196,24 @@ func (p *Provider) addServerTCP(ctx context.Context, container dockerData, loadB
return errors.New("load-balancer is not defined") return errors.New("load-balancer is not defined")
} }
var serverPort string if len(loadBalancer.Servers) == 0 {
if len(loadBalancer.Servers) > 0 { loadBalancer.Servers = []dynamic.TCPServer{{}}
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
} }
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(ctx, container, serverPort) ip, port, err := p.getIPPort(ctx, container, serverPort)
if err != nil { if err != nil {
return err return err
} }
if len(loadBalancer.Servers) == 0 {
server := dynamic.TCPServer{}
loadBalancer.Servers = []dynamic.TCPServer{server}
}
if port == "" { if port == "" {
return errors.New("port is missing") return errors.New("port is missing")
} }
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port) loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
return nil return nil
} }
@ -226,28 +222,24 @@ func (p *Provider) addServerUDP(ctx context.Context, container dockerData, loadB
return errors.New("load-balancer is not defined") return errors.New("load-balancer is not defined")
} }
var serverPort string if len(loadBalancer.Servers) == 0 {
if len(loadBalancer.Servers) > 0 { loadBalancer.Servers = []dynamic.UDPServer{{}}
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
} }
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(ctx, container, serverPort) ip, port, err := p.getIPPort(ctx, container, serverPort)
if err != nil { if err != nil {
return err return err
} }
if len(loadBalancer.Servers) == 0 {
server := dynamic.UDPServer{}
loadBalancer.Servers = []dynamic.UDPServer{server}
}
if port == "" { if port == "" {
return errors.New("port is missing") return errors.New("port is missing")
} }
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port) loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
return nil return nil
} }
@ -256,17 +248,6 @@ func (p *Provider) addServer(ctx context.Context, container dockerData, loadBala
return errors.New("load-balancer is not defined") return errors.New("load-balancer is not defined")
} }
var serverPort string
if len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
}
ip, port, err := p.getIPPort(ctx, container, serverPort)
if err != nil {
return err
}
if len(loadBalancer.Servers) == 0 { if len(loadBalancer.Servers) == 0 {
server := dynamic.Server{} server := dynamic.Server{}
server.SetDefaults() server.SetDefaults()
@ -274,6 +255,14 @@ func (p *Provider) addServer(ctx context.Context, container dockerData, loadBala
loadBalancer.Servers = []dynamic.Server{server} loadBalancer.Servers = []dynamic.Server{server}
} }
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(ctx, container, serverPort)
if err != nil {
return err
}
if port == "" { if port == "" {
return errors.New("port is missing") return errors.New("port is missing")
} }

View file

@ -185,7 +185,7 @@ func (p *Provider) filterInstance(ctx context.Context, instance ecsInstance) boo
matches, err := constraints.MatchLabels(instance.Labels, p.Constraints) matches, err := constraints.MatchLabels(instance.Labels, p.Constraints)
if err != nil { if err != nil {
logger.Errorf("Error matching constraints expression: %v", err) logger.Errorf("Error matching constraint expression: %v", err)
return false return false
} }
if !matches { if !matches {
@ -201,28 +201,24 @@ func (p *Provider) addServerTCP(instance ecsInstance, loadBalancer *dynamic.TCPS
return errors.New("load-balancer is not defined") return errors.New("load-balancer is not defined")
} }
var serverPort string if len(loadBalancer.Servers) == 0 {
if len(loadBalancer.Servers) > 0 { loadBalancer.Servers = []dynamic.TCPServer{{}}
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
} }
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(instance, serverPort) ip, port, err := p.getIPPort(instance, serverPort)
if err != nil { if err != nil {
return err return err
} }
if len(loadBalancer.Servers) == 0 {
server := dynamic.TCPServer{}
loadBalancer.Servers = []dynamic.TCPServer{server}
}
if port == "" { if port == "" {
return errors.New("port is missing") return errors.New("port is missing")
} }
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port) loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
return nil return nil
} }
@ -231,28 +227,24 @@ func (p *Provider) addServerUDP(instance ecsInstance, loadBalancer *dynamic.UDPS
return errors.New("load-balancer is not defined") return errors.New("load-balancer is not defined")
} }
var serverPort string if len(loadBalancer.Servers) == 0 {
if len(loadBalancer.Servers) > 0 { loadBalancer.Servers = []dynamic.UDPServer{{}}
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
} }
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(instance, serverPort) ip, port, err := p.getIPPort(instance, serverPort)
if err != nil { if err != nil {
return err return err
} }
if len(loadBalancer.Servers) == 0 {
server := dynamic.UDPServer{}
loadBalancer.Servers = []dynamic.UDPServer{server}
}
if port == "" { if port == "" {
return errors.New("port is missing") return errors.New("port is missing")
} }
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port) loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
return nil return nil
} }
@ -261,17 +253,6 @@ func (p *Provider) addServer(instance ecsInstance, loadBalancer *dynamic.Servers
return errors.New("load-balancer is not defined") return errors.New("load-balancer is not defined")
} }
var serverPort string
if len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
}
ip, port, err := p.getIPPort(instance, serverPort)
if err != nil {
return err
}
if len(loadBalancer.Servers) == 0 { if len(loadBalancer.Servers) == 0 {
server := dynamic.Server{} server := dynamic.Server{}
server.SetDefaults() server.SetDefaults()
@ -279,6 +260,14 @@ func (p *Provider) addServer(instance ecsInstance, loadBalancer *dynamic.Servers
loadBalancer.Servers = []dynamic.Server{server} loadBalancer.Servers = []dynamic.Server{server}
} }
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(instance, serverPort)
if err != nil {
return err
}
if port == "" { if port == "" {
return errors.New("port is missing") return errors.New("port is missing")
} }

View file

@ -175,29 +175,27 @@ func (p *Provider) addServerTCP(i item, lb *dynamic.TCPServersLoadBalancer) erro
return errors.New("load-balancer is missing") return errors.New("load-balancer is missing")
} }
var port string
if len(lb.Servers) > 0 {
port = lb.Servers[0].Port
}
if len(lb.Servers) == 0 { if len(lb.Servers) == 0 {
lb.Servers = []dynamic.TCPServer{{}} lb.Servers = []dynamic.TCPServer{{}}
} }
if i.Port != 0 && port == "" {
port = strconv.Itoa(i.Port)
}
lb.Servers[0].Port = ""
if port == "" {
return errors.New("port is missing")
}
if i.Address == "" { if i.Address == "" {
return errors.New("address is missing") return errors.New("address is missing")
} }
port := lb.Servers[0].Port
lb.Servers[0].Port = ""
if port == "" && i.Port > 0 {
port = strconv.Itoa(i.Port)
}
if port == "" {
return errors.New("port is missing")
}
lb.Servers[0].Address = net.JoinHostPort(i.Address, port) lb.Servers[0].Address = net.JoinHostPort(i.Address, port)
return nil return nil
} }
@ -206,29 +204,27 @@ func (p *Provider) addServerUDP(i item, lb *dynamic.UDPServersLoadBalancer) erro
return errors.New("load-balancer is missing") return errors.New("load-balancer is missing")
} }
var port string
if len(lb.Servers) > 0 {
port = lb.Servers[0].Port
}
if len(lb.Servers) == 0 { if len(lb.Servers) == 0 {
lb.Servers = []dynamic.UDPServer{{}} lb.Servers = []dynamic.UDPServer{{}}
} }
if i.Port != 0 && port == "" {
port = strconv.Itoa(i.Port)
}
lb.Servers[0].Port = ""
if port == "" {
return errors.New("port is missing")
}
if i.Address == "" { if i.Address == "" {
return errors.New("address is missing") return errors.New("address is missing")
} }
port := lb.Servers[0].Port
lb.Servers[0].Port = ""
if port == "" && i.Port > 0 {
port = strconv.Itoa(i.Port)
}
if port == "" {
return errors.New("port is missing")
}
lb.Servers[0].Address = net.JoinHostPort(i.Address, port) lb.Servers[0].Address = net.JoinHostPort(i.Address, port)
return nil return nil
} }
@ -237,11 +233,6 @@ func (p *Provider) addServer(i item, lb *dynamic.ServersLoadBalancer) error {
return errors.New("load-balancer is missing") return errors.New("load-balancer is missing")
} }
var port string
if len(lb.Servers) > 0 {
port = lb.Servers[0].Port
}
if len(lb.Servers) == 0 { if len(lb.Servers) == 0 {
server := dynamic.Server{} server := dynamic.Server{}
server.SetDefaults() server.SetDefaults()
@ -249,19 +240,21 @@ func (p *Provider) addServer(i item, lb *dynamic.ServersLoadBalancer) error {
lb.Servers = []dynamic.Server{server} lb.Servers = []dynamic.Server{server}
} }
if i.Port != 0 && port == "" { if i.Address == "" {
return errors.New("address is missing")
}
port := lb.Servers[0].Port
lb.Servers[0].Port = ""
if port == "" && i.Port > 0 {
port = strconv.Itoa(i.Port) port = strconv.Itoa(i.Port)
} }
lb.Servers[0].Port = ""
if port == "" { if port == "" {
return errors.New("port is missing") return errors.New("port is missing")
} }
if i.Address == "" {
return errors.New("address is missing")
}
scheme := lb.Servers[0].Scheme scheme := lb.Servers[0].Scheme
lb.Servers[0].Scheme = "" lb.Servers[0].Scheme = ""
lb.Servers[0].URL = fmt.Sprintf("%s://%s", scheme, net.JoinHostPort(i.Address, port)) lb.Servers[0].URL = fmt.Sprintf("%s://%s", scheme, net.JoinHostPort(i.Address, port))

View file

@ -160,7 +160,7 @@ func (p *Provider) keepService(ctx context.Context, service rancherData) bool {
matches, err := constraints.MatchLabels(service.Labels, p.Constraints) matches, err := constraints.MatchLabels(service.Labels, p.Constraints)
if err != nil { if err != nil {
logger.Errorf("Error matching constraints expression: %v", err) logger.Errorf("Error matching constraint expression: %v", err)
return false return false
} }
if !matches { if !matches {
@ -185,23 +185,19 @@ func (p *Provider) keepService(ctx context.Context, service rancherData) bool {
func (p *Provider) addServerTCP(ctx context.Context, service rancherData, loadBalancer *dynamic.TCPServersLoadBalancer) error { func (p *Provider) addServerTCP(ctx context.Context, service rancherData, loadBalancer *dynamic.TCPServersLoadBalancer) error {
log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name) log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name)
serverPort := "" if loadBalancer == nil {
return errors.New("load-balancer is not defined")
if loadBalancer != nil && len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
} }
port := getServicePort(service)
if len(loadBalancer.Servers) == 0 { if len(loadBalancer.Servers) == 0 {
server := dynamic.TCPServer{} loadBalancer.Servers = []dynamic.TCPServer{{}}
loadBalancer.Servers = []dynamic.TCPServer{server}
} }
if serverPort != "" { port := loadBalancer.Servers[0].Port
port = serverPort loadBalancer.Servers[0].Port = ""
loadBalancer.Servers[0].Port = ""
if port == "" {
port = getServicePort(service)
} }
if port == "" { if port == "" {
@ -216,29 +212,26 @@ func (p *Provider) addServerTCP(ctx context.Context, service rancherData, loadBa
} }
loadBalancer.Servers = servers loadBalancer.Servers = servers
return nil return nil
} }
func (p *Provider) addServerUDP(ctx context.Context, service rancherData, loadBalancer *dynamic.UDPServersLoadBalancer) error { func (p *Provider) addServerUDP(ctx context.Context, service rancherData, loadBalancer *dynamic.UDPServersLoadBalancer) error {
log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name) log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name)
serverPort := "" if loadBalancer == nil {
return errors.New("load-balancer is not defined")
if loadBalancer != nil && len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
} }
port := getServicePort(service)
if len(loadBalancer.Servers) == 0 { if len(loadBalancer.Servers) == 0 {
server := dynamic.UDPServer{} loadBalancer.Servers = []dynamic.UDPServer{{}}
loadBalancer.Servers = []dynamic.UDPServer{server}
} }
if serverPort != "" { port := loadBalancer.Servers[0].Port
port = serverPort loadBalancer.Servers[0].Port = ""
loadBalancer.Servers[0].Port = ""
if port == "" {
port = getServicePort(service)
} }
if port == "" { if port == "" {
@ -253,14 +246,16 @@ func (p *Provider) addServerUDP(ctx context.Context, service rancherData, loadBa
} }
loadBalancer.Servers = servers loadBalancer.Servers = servers
return nil return nil
} }
func (p *Provider) addServers(ctx context.Context, service rancherData, loadBalancer *dynamic.ServersLoadBalancer) error { func (p *Provider) addServers(ctx context.Context, service rancherData, loadBalancer *dynamic.ServersLoadBalancer) error {
log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name) log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name)
serverPort := getLBServerPort(loadBalancer) if loadBalancer == nil {
port := getServicePort(service) return errors.New("load-balancer is not defined")
}
if len(loadBalancer.Servers) == 0 { if len(loadBalancer.Servers) == 0 {
server := dynamic.Server{} server := dynamic.Server{}
@ -269,9 +264,11 @@ func (p *Provider) addServers(ctx context.Context, service rancherData, loadBala
loadBalancer.Servers = []dynamic.Server{server} loadBalancer.Servers = []dynamic.Server{server}
} }
if serverPort != "" { port := loadBalancer.Servers[0].Port
port = serverPort loadBalancer.Servers[0].Port = ""
loadBalancer.Servers[0].Port = ""
if port == "" {
port = getServicePort(service)
} }
if port == "" { if port == "" {
@ -286,14 +283,8 @@ func (p *Provider) addServers(ctx context.Context, service rancherData, loadBala
} }
loadBalancer.Servers = servers loadBalancer.Servers = servers
return nil
}
func getLBServerPort(loadBalancer *dynamic.ServersLoadBalancer) string { return nil
if loadBalancer != nil && len(loadBalancer.Servers) > 0 {
return loadBalancer.Servers[0].Port
}
return ""
} }
func getServicePort(data rancherData) string { func getServicePort(data rancherData) string {

View file

@ -15,6 +15,7 @@ import (
ptypes "github.com/traefik/paerser/types" ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/dynamic"
"github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/log"
"golang.org/x/net/http/httpguts"
) )
// StatusClientClosedRequest non-standard HTTP status code for client disconnection. // StatusClientClosedRequest non-standard HTTP status code for client disconnection.
@ -67,16 +68,18 @@ func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwar
// some servers need Sec-WebSocket-Key, Sec-WebSocket-Extensions, Sec-WebSocket-Accept, // some servers need Sec-WebSocket-Key, Sec-WebSocket-Extensions, Sec-WebSocket-Accept,
// Sec-WebSocket-Protocol and Sec-WebSocket-Version to be case-sensitive. // Sec-WebSocket-Protocol and Sec-WebSocket-Version to be case-sensitive.
// https://tools.ietf.org/html/rfc6455#page-20 // https://tools.ietf.org/html/rfc6455#page-20
outReq.Header["Sec-WebSocket-Key"] = outReq.Header["Sec-Websocket-Key"] if isWebSocketUpgrade(outReq) {
outReq.Header["Sec-WebSocket-Extensions"] = outReq.Header["Sec-Websocket-Extensions"] outReq.Header["Sec-WebSocket-Key"] = outReq.Header["Sec-Websocket-Key"]
outReq.Header["Sec-WebSocket-Accept"] = outReq.Header["Sec-Websocket-Accept"] outReq.Header["Sec-WebSocket-Extensions"] = outReq.Header["Sec-Websocket-Extensions"]
outReq.Header["Sec-WebSocket-Protocol"] = outReq.Header["Sec-Websocket-Protocol"] outReq.Header["Sec-WebSocket-Accept"] = outReq.Header["Sec-Websocket-Accept"]
outReq.Header["Sec-WebSocket-Version"] = outReq.Header["Sec-Websocket-Version"] outReq.Header["Sec-WebSocket-Protocol"] = outReq.Header["Sec-Websocket-Protocol"]
delete(outReq.Header, "Sec-Websocket-Key") outReq.Header["Sec-WebSocket-Version"] = outReq.Header["Sec-Websocket-Version"]
delete(outReq.Header, "Sec-Websocket-Extensions") delete(outReq.Header, "Sec-Websocket-Key")
delete(outReq.Header, "Sec-Websocket-Accept") delete(outReq.Header, "Sec-Websocket-Extensions")
delete(outReq.Header, "Sec-Websocket-Protocol") delete(outReq.Header, "Sec-Websocket-Accept")
delete(outReq.Header, "Sec-Websocket-Version") delete(outReq.Header, "Sec-Websocket-Protocol")
delete(outReq.Header, "Sec-Websocket-Version")
}
}, },
Transport: roundTripper, Transport: roundTripper,
FlushInterval: time.Duration(flushInterval), FlushInterval: time.Duration(flushInterval),
@ -112,6 +115,14 @@ func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwar
return proxy, nil return proxy, nil
} }
func isWebSocketUpgrade(req *http.Request) bool {
if !httpguts.HeaderValuesContainsToken(req.Header["Connection"], "Upgrade") {
return false
}
return strings.EqualFold(req.Header.Get("Upgrade"), "websocket")
}
func statusText(statusCode int) string { func statusText(statusCode int) string {
if statusCode == StatusClientClosedRequest { if statusCode == StatusClientClosedRequest {
return StatusClientClosedRequestText return StatusClientClosedRequestText