Merge remote-tracking branch 'upstream/v2.2' into mrg-current-v2.2

This commit is contained in:
jb doumenjou 2020-06-15 11:22:51 +02:00
commit 7affeae480
12 changed files with 136 additions and 55 deletions

View file

@ -282,7 +282,7 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used
|-------------------------------------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------| |-------------------------------------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------|
| [ACME DNS](https://github.com/joohoi/acme-dns) | `acme-dns` | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns) | | [ACME DNS](https://github.com/joohoi/acme-dns) | `acme-dns` | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns) |
| [Alibaba Cloud](https://www.alibabacloud.com) | `alidns` | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/alidns) | | [Alibaba Cloud](https://www.alibabacloud.com) | `alidns` | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/alidns) |
| [Auroradns](https://www.pcextreme.com/aurora/dns) | `auroradns` | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns) | | [Auroradns](https://www.pcextreme.com/dns-health-checks) | `auroradns` | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns) |
| [Autodns](https://www.internetx.com/domains/autodns/) | `autodns` | `AUTODNS_API_USER`, `AUTODNS_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/autodns) | | [Autodns](https://www.internetx.com/domains/autodns/) | `autodns` | `AUTODNS_API_USER`, `AUTODNS_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/autodns) |
| [Azure](https://azure.microsoft.com/services/dns/) | `azure` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]` | [Additional configuration](https://go-acme.github.io/lego/dns/azure) | | [Azure](https://azure.microsoft.com/services/dns/) | `azure` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]` | [Additional configuration](https://go-acme.github.io/lego/dns/azure) |
| [Bindman](https://github.com/labbsr0x/bindman-dns-webhook) | `bindman` | `BINDMAN_MANAGER_ADDRESS` | [Additional configuration](https://go-acme.github.io/lego/dns/bindman) | | [Bindman](https://github.com/labbsr0x/bindman-dns-webhook) | `bindman` | `BINDMAN_MANAGER_ADDRESS` | [Additional configuration](https://go-acme.github.io/lego/dns/bindman) |

View file

@ -311,7 +311,7 @@ This value can contains a list of allowed origins.
More information including how to use the settings can be found on: More information including how to use the settings can be found on:
- [Mozilla.org](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) - [Mozilla.org](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin)
- [w3](https://www.w3.org/TR/cors/#access-control-allow-origin-response-header) - [w3](https://fetch.spec.whatwg.org/#http-access-control-allow-origin)
- [IETF](https://tools.ietf.org/html/rfc6454#section-7.1) - [IETF](https://tools.ietf.org/html/rfc6454#section-7.1)
Traefik no longer supports the null value, as it is [no longer recommended as a return value](https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null). Traefik no longer supports the null value, as it is [no longer recommended as a return value](https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null).

View file

@ -97,7 +97,7 @@ Then any router can refer to an instance of the wanted middleware.
```yaml tab="Docker" ```yaml tab="Docker"
labels: labels:
- "traefik.http.routers.router0.rule=Host(`example.com`) && PathPrefix(`/test`)" - "traefik.http.routers.router0.rule=Host(`test.localhost`) && PathPrefix(`/test`)"
- "traefik.http.routers.router0.middlewares=auth" - "traefik.http.routers.router0.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
``` ```

View file

@ -111,9 +111,9 @@ accessLog:
--accesslog.filters.minduration=10ms --accesslog.filters.minduration=10ms
``` ```
### Limiting the Fields ### Limiting the Fields/Including Headers
You can decide to limit the logged fields/headers to a given list with the `fields.names` and `fields.header` options You can decide to limit the logged fields/headers to a given list with the `fields.names` and `fields.headers` options.
Each field can be set to: Each field can be set to:
@ -121,7 +121,7 @@ Each field can be set to:
- `drop` to drop the value - `drop` to drop the value
- `redact` to replace the value with "redacted" - `redact` to replace the value with "redacted"
The `defaultMode` for `fields.header` is `drop`. The `defaultMode` for `fields.headers` is `drop`.
```toml tab="File (TOML)" ```toml tab="File (TOML)"
# Limiting the Logs to Specific Fields # Limiting the Logs to Specific Fields

View file

@ -154,7 +154,7 @@ You can specify which Docker API Endpoint to use with the directive [`endpoint`]
- Authentication with Client Certificates as described in ["Protect the Docker daemon socket."](https://docs.docker.com/engine/security/https/) - Authentication with Client Certificates as described in ["Protect the Docker daemon socket."](https://docs.docker.com/engine/security/https/)
- Authorize and filter requests to restrict possible actions with [the TecnativaDocker Socket Proxy](https://github.com/Tecnativa/docker-socket-proxy). - Authorize and filter requests to restrict possible actions with [the TecnativaDocker Socket Proxy](https://github.com/Tecnativa/docker-socket-proxy).
- Authorization with the [Docker Authorization Plugin Mechanism](https://docs.docker.com/engine/extend/plugins_authorization/) - Authorization with the [Docker Authorization Plugin Mechanism](https://web.archive.org/web/20190920092526/https://docs.docker.com/engine/extend/plugins_authorization/)
- Accounting at networking level, by exposing the socket only inside a Docker private network, only available for Traefik. - Accounting at networking level, by exposing the socket only inside a Docker private network, only available for Traefik.
- Accounting at container level, by exposing the socket on a another container than Traefik's. - Accounting at container level, by exposing the socket on a another container than Traefik's.
With Swarm mode, it allows scheduling of Traefik on worker nodes, with only the "socket exposer" container on the manager nodes. With Swarm mode, it allows scheduling of Traefik on worker nodes, with only the "socket exposer" container on the manager nodes.

View file

@ -291,7 +291,7 @@ you'd add the label `traefik.http.services.<name-of-your-choice>.loadbalancer.pa
See [health check](../services/index.md#health-check) for more information. See [health check](../services/index.md#health-check) for more information.
```yaml ```yaml
- "traefik.http.services.myservice.loadbalancer.healthcheck.interval=10" - "traefik.http.services.myservice.loadbalancer.healthcheck.interval=10s"
``` ```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.path`" ??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.path`"

View file

@ -108,24 +108,24 @@ The Kubernetes Ingress Controller, The Custom Resource Way.
name: myingressroute name: myingressroute
namespace: default namespace: default
spec: spec:
entryPoints: entryPoints:
- web - web
routes: routes:
- match: Host(`foo`) && PathPrefix(`/bar`) - match: Host(`foo`) && PathPrefix(`/bar`)
kind: Rule kind: Rule
services: services:
- name: whoami - name: whoami
port: 80 port: 80
--- ---
apiVersion: traefik.containo.us/v1alpha1 apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP kind: IngressRouteTCP
metadata: metadata:
name: ingressroute.tcp name: ingressroute.tcp
namespace: default namespace: default
spec: spec:
entryPoints: entryPoints:
- tcpep - tcpep
@ -135,22 +135,22 @@ The Kubernetes Ingress Controller, The Custom Resource Way.
services: services:
- name: whoamitcp - name: whoamitcp
port: 8080 port: 8080
--- ---
apiVersion: traefik.containo.us/v1alpha1 apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteUDP kind: IngressRouteUDP
metadata: metadata:
name: ingressroute.udp name: ingressroute.udp
namespace: default namespace: default
spec: spec:
entryPoints: entryPoints:
- fooudp - fooudp
routes: routes:
- kind: Rule - kind: Rule
services: services:
- name: whoamiudp - name: whoamiudp
port: 8080 port: 8080
``` ```
```yaml tab="Whoami" ```yaml tab="Whoami"

View file

@ -202,7 +202,7 @@ which in turn will create the resulting routers, services, handlers, etc.
See [middlewares](../routers/index.md#middlewares) and [middlewares overview](../../middlewares/overview.md) for more information. See [middlewares](../routers/index.md#middlewares) and [middlewares overview](../../middlewares/overview.md) for more information.
```yaml ```yaml
traefik.ingress.kubernetes.io/router.middlewares: auth@file,prefix@kuberntescrd,cb@file traefik.ingress.kubernetes.io/router.middlewares: auth@file,prefix@kubernetescrd,cb@file
``` ```
??? info "`traefik.ingress.kubernetes.io/router.priority`" ??? info "`traefik.ingress.kubernetes.io/router.priority`"

View file

@ -132,18 +132,18 @@ func (x *XForwarded) rewrite(outreq *http.Request) {
xfProto := outreq.Header.Get(xForwardedProto) xfProto := outreq.Header.Get(xForwardedProto)
if xfProto == "" { if xfProto == "" {
if outreq.TLS != nil { if isWebsocketRequest(outreq) {
outreq.Header.Set(xForwardedProto, "https") if outreq.TLS != nil {
outreq.Header.Set(xForwardedProto, "wss")
} else {
outreq.Header.Set(xForwardedProto, "ws")
}
} else { } else {
outreq.Header.Set(xForwardedProto, "http") if outreq.TLS != nil {
} outreq.Header.Set(xForwardedProto, "https")
} } else {
outreq.Header.Set(xForwardedProto, "http")
if isWebsocketRequest(outreq) { }
if outreq.Header.Get(xForwardedProto) == "https" || outreq.Header.Get(xForwardedProto) == "wss" {
outreq.Header.Set(xForwardedProto, "wss")
} else {
outreq.Header.Set(xForwardedProto, "ws")
} }
} }

View file

@ -345,7 +345,23 @@ func (p Provider) getIPAddress(ctx context.Context, container dockerData) string
logger.Warnf("Unable to get IP address for container %s : Failed to inspect container ID %s, error: %s", container.Name, connectedContainer, err) logger.Warnf("Unable to get IP address for container %s : Failed to inspect container ID %s, error: %s", container.Name, connectedContainer, err)
return "" return ""
} }
return p.getIPAddress(ctx, parseContainer(containerInspected))
// Check connected container for traefik.docker.network, falling back to
// the network specified on the current container.
containerParsed := parseContainer(containerInspected)
extraConf, err := p.getConfiguration(containerParsed)
if err != nil {
logger.Warnf("Unable to get IP address for container %s : failed to get extra configuration for container %s: %s", container.Name, containerInspected.Name, err)
return ""
}
if extraConf.Docker.Network == "" {
extraConf.Docker.Network = container.ExtraConf.Docker.Network
}
containerParsed.ExtraConf = extraConf
return p.getIPAddress(ctx, containerParsed)
} }
for _, network := range container.NetworkSettings.Networks { for _, network := range container.NetworkSettings.Networks {

View file

@ -128,9 +128,11 @@ func (l *Listener) Shutdown(graceTimeout time.Duration) error {
// we find that session, and otherwise we create a new one. // we find that session, and otherwise we create a new one.
// We then send the data the session's readLoop. // We then send the data the session's readLoop.
func (l *Listener) readLoop() { func (l *Listener) readLoop() {
buf := make([]byte, receiveMTU)
for { for {
// Allocating a new buffer for every read avoids
// overwriting data in c.msgs in case the next packet is received
// before c.msgs is emptied via Read()
buf := make([]byte, receiveMTU)
n, raddr, err := l.pConn.ReadFrom(buf) n, raddr, err := l.pConn.ReadFrom(buf)
if err != nil { if err != nil {
return return
@ -177,7 +179,7 @@ func (l *Listener) newConn(rAddr net.Addr) *Conn {
readCh: make(chan []byte), readCh: make(chan []byte),
sizeCh: make(chan int), sizeCh: make(chan int),
doneCh: make(chan struct{}), doneCh: make(chan struct{}),
ticker: time.NewTicker(timeoutTicker), timeout: timeoutTicker,
} }
} }
@ -194,7 +196,7 @@ type Conn struct {
muActivity sync.RWMutex muActivity sync.RWMutex
lastActivity time.Time // the last time the session saw either read or write activity lastActivity time.Time // the last time the session saw either read or write activity
ticker *time.Ticker // for timeouts timeout time.Duration // for timeouts
doneOnce sync.Once doneOnce sync.Once
doneCh chan struct{} doneCh chan struct{}
} }
@ -204,12 +206,15 @@ type Conn struct {
// that is to say it waits on readCh to receive the slice of bytes that the Read operation wants to read onto. // that is to say it waits on readCh to receive the slice of bytes that the Read operation wants to read onto.
// The Read operation receives the signal that the data has been written to the slice of bytes through the sizeCh. // The Read operation receives the signal that the data has been written to the slice of bytes through the sizeCh.
func (c *Conn) readLoop() { func (c *Conn) readLoop() {
ticker := time.NewTicker(c.timeout)
defer ticker.Stop()
for { for {
if len(c.msgs) == 0 { if len(c.msgs) == 0 {
select { select {
case msg := <-c.receiveCh: case msg := <-c.receiveCh:
c.msgs = append(c.msgs, msg) c.msgs = append(c.msgs, msg)
case <-c.ticker.C: case <-ticker.C:
c.muActivity.RLock() c.muActivity.RLock()
deadline := c.lastActivity.Add(connTimeout) deadline := c.lastActivity.Add(connTimeout)
c.muActivity.RUnlock() c.muActivity.RUnlock()
@ -229,7 +234,7 @@ func (c *Conn) readLoop() {
c.sizeCh <- n c.sizeCh <- n
case msg := <-c.receiveCh: case msg := <-c.receiveCh:
c.msgs = append(c.msgs, msg) c.msgs = append(c.msgs, msg)
case <-c.ticker.C: case <-ticker.C:
c.muActivity.RLock() c.muActivity.RLock()
deadline := c.lastActivity.Add(connTimeout) deadline := c.lastActivity.Add(connTimeout)
c.muActivity.RUnlock() c.muActivity.RUnlock()
@ -281,6 +286,5 @@ func (c *Conn) Close() error {
c.listener.mu.Lock() c.listener.mu.Lock()
defer c.listener.mu.Unlock() defer c.listener.mu.Unlock()
delete(c.listener.conns, c.rAddr.String()) delete(c.listener.conns, c.rAddr.String())
c.ticker.Stop()
return nil return nil
} }

View file

@ -10,6 +10,67 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestConsecutiveWrites(t *testing.T) {
addr, err := net.ResolveUDPAddr("udp", ":0")
require.NoError(t, err)
ln, err := Listen("udp", addr)
require.NoError(t, err)
defer func() {
err := ln.Close()
require.NoError(t, err)
}()
go func() {
for {
conn, err := ln.Accept()
if err == errClosedListener {
return
}
require.NoError(t, err)
go func() {
b := make([]byte, 2048)
b2 := make([]byte, 2048)
var n int
var n2 int
n, err = conn.Read(b)
require.NoError(t, err)
// Wait to make sure that the second packet is received
time.Sleep(10 * time.Millisecond)
n2, err = conn.Read(b2)
require.NoError(t, err)
_, err = conn.Write(b[:n])
require.NoError(t, err)
_, err = conn.Write(b2[:n2])
require.NoError(t, err)
}()
}
}()
udpConn, err := net.Dial("udp", ln.Addr().String())
require.NoError(t, err)
// Send multiple packets of different content and length consecutively
// Read back packets afterwards and make sure that content matches
// This checks if any buffers are overwritten while the receiver is enqueuing multiple packets
b := make([]byte, 2048)
var n int
_, err = udpConn.Write([]byte("TESTLONG0"))
require.NoError(t, err)
_, err = udpConn.Write([]byte("1TEST"))
require.NoError(t, err)
n, err = udpConn.Read(b)
require.NoError(t, err)
require.Equal(t, "TESTLONG0", string(b[:n]))
n, err = udpConn.Read(b)
require.NoError(t, err)
require.Equal(t, "1TEST", string(b[:n]))
}
func TestListenNotBlocking(t *testing.T) { func TestListenNotBlocking(t *testing.T) {
addr, err := net.ResolveUDPAddr("udp", ":0") addr, err := net.ResolveUDPAddr("udp", ":0")