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) |
| [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) |
| [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) |

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:
- [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)
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"
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.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
```

View file

@ -111,9 +111,9 @@ accessLog:
--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:
@ -121,7 +121,7 @@ Each field can be set to:
- `drop` to drop the value
- `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)"
# 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/)
- 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 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.

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.
```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`"

View file

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

View file

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

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)
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 {

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 then send the data the session's readLoop.
func (l *Listener) readLoop() {
buf := make([]byte, receiveMTU)
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)
if err != nil {
return
@ -177,7 +179,7 @@ func (l *Listener) newConn(rAddr net.Addr) *Conn {
readCh: make(chan []byte),
sizeCh: make(chan int),
doneCh: make(chan struct{}),
ticker: time.NewTicker(timeoutTicker),
timeout: timeoutTicker,
}
}
@ -194,7 +196,7 @@ type Conn struct {
muActivity sync.RWMutex
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
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.
// The Read operation receives the signal that the data has been written to the slice of bytes through the sizeCh.
func (c *Conn) readLoop() {
ticker := time.NewTicker(c.timeout)
defer ticker.Stop()
for {
if len(c.msgs) == 0 {
select {
case msg := <-c.receiveCh:
c.msgs = append(c.msgs, msg)
case <-c.ticker.C:
case <-ticker.C:
c.muActivity.RLock()
deadline := c.lastActivity.Add(connTimeout)
c.muActivity.RUnlock()
@ -229,7 +234,7 @@ func (c *Conn) readLoop() {
c.sizeCh <- n
case msg := <-c.receiveCh:
c.msgs = append(c.msgs, msg)
case <-c.ticker.C:
case <-ticker.C:
c.muActivity.RLock()
deadline := c.lastActivity.Add(connTimeout)
c.muActivity.RUnlock()
@ -281,6 +286,5 @@ func (c *Conn) Close() error {
c.listener.mu.Lock()
defer c.listener.mu.Unlock()
delete(c.listener.conns, c.rAddr.String())
c.ticker.Stop()
return nil
}

View file

@ -10,6 +10,67 @@ import (
"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) {
addr, err := net.ResolveUDPAddr("udp", ":0")