1
0
Fork 0

Merge current v2.8 into master

This commit is contained in:
kevinpollet 2022-08-18 14:50:44 +02:00
commit 626da4c0ae
No known key found for this signature in database
GPG key ID: 0C9A5DDD1B292453
90 changed files with 1019 additions and 707 deletions

View file

@ -469,9 +469,8 @@ func (d *dynamicConfig) hasServerURL(serviceName, serverURL string) bool {
func newCounterFrom(opts stdprometheus.CounterOpts, labelNames []string) *counter {
cv := stdprometheus.NewCounterVec(opts, labelNames)
c := &counter{
name: opts.Name,
cv: cv,
labelNamesValues: make([]string, 0, 16),
name: opts.Name,
cv: cv,
}
if len(labelNames) == 0 {
c.collector = cv.WithLabelValues()
@ -508,9 +507,8 @@ func (c *counter) Describe(ch chan<- *stdprometheus.Desc) {
func newGaugeFrom(opts stdprometheus.GaugeOpts, labelNames []string) *gauge {
gv := stdprometheus.NewGaugeVec(opts, labelNames)
g := &gauge{
name: opts.Name,
gv: gv,
labelNamesValues: make([]string, 0, 16),
name: opts.Name,
gv: gv,
}
if len(labelNames) == 0 {
@ -552,9 +550,8 @@ func (g *gauge) Describe(ch chan<- *stdprometheus.Desc) {
func newHistogramFrom(opts stdprometheus.HistogramOpts, labelNames []string) *histogram {
hv := stdprometheus.NewHistogramVec(opts, labelNames)
return &histogram{
name: opts.Name,
hv: hv,
labelNamesValues: make([]string, 0, 16),
name: opts.Name,
hv: hv,
}
}
@ -593,7 +590,12 @@ func (lvs labelNamesValues) With(labelValues ...string) labelNamesValues {
if len(labelValues)%2 != 0 {
labelValues = append(labelValues, "unknown")
}
return append(lvs, labelValues...)
labels := make([]string, len(lvs)+len(labelValues))
n := copy(labels, lvs)
copy(labels[n:], labelValues)
return labels
}
// ToLabels is a convenience method to convert a labelNamesValues

View file

@ -401,7 +401,7 @@ func BenchmarkCompress(b *testing.B) {
})
handler, _ := New(context.Background(), next, dynamic.Compress{}, "testing")
req, _ := http.NewRequest("GET", "/whatever", nil)
req, _ := http.NewRequest(http.MethodGet, "/whatever", nil)
req.Header.Set("Accept-Encoding", "gzip")
b.ReportAllocs()

View file

@ -63,15 +63,16 @@ func (wl *ipWhiteLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
ctx := middlewares.GetLoggerCtx(req.Context(), wl.name, typeName)
logger := log.FromContext(ctx)
err := wl.whiteLister.IsAuthorized(wl.strategy.GetIP(req))
clientIP := wl.strategy.GetIP(req)
err := wl.whiteLister.IsAuthorized(clientIP)
if err != nil {
logMessage := fmt.Sprintf("rejecting request %+v: %v", req, err)
logger.Debug(logMessage)
tracing.SetErrorWithEvent(req, logMessage)
msg := fmt.Sprintf("Rejecting IP %s: %v", clientIP, err)
logger.Debug(msg)
tracing.SetErrorWithEvent(req, msg)
reject(ctx, rw)
return
}
logger.Debugf("Accept %s: %+v", wl.strategy.GetIP(req), req)
logger.Debugf("Accepting IP %s", clientIP)
wl.next.ServeHTTP(rw, req)
}

View file

@ -222,7 +222,7 @@ func (l *countingRetryListener) Retried(req *http.Request, attempt int) {
func TestRetryWithFlush(t *testing.T) {
next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(200)
rw.WriteHeader(http.StatusOK)
_, err := rw.Write([]byte("FULL "))
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)

View file

@ -86,7 +86,7 @@ func (p middlewareBuilder) createConfig(config map[string]interface{}) (reflect.
vConfig := results[0]
cfg := &mapstructure.DecoderConfig{
DecodeHook: stringToSliceHookFunc,
DecodeHook: mapstructure.StringToSliceHookFunc(","),
WeaklyTypedInput: true,
Result: vConfig.Interface(),
}

View file

@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"reflect"
"strings"
"github.com/hashicorp/go-multierror"
@ -167,26 +166,3 @@ func checkLocalPluginManifest(descriptor LocalDescriptor) error {
return errs.ErrorOrNil()
}
func stringToSliceHookFunc(f reflect.Kind, t reflect.Kind, data interface{}) (interface{}, error) {
if f != reflect.String || t != reflect.Slice {
return data, nil
}
raw := data.(string)
if raw == "" {
return []string{}, nil
}
if strings.Contains(raw, "║") {
values := strings.Split(raw, "║")
// Removes the first value if the slice has a length of 2 and a first value empty.
// It's a workaround to escape the parsing on `,`.
if len(values) == 2 && values[0] == "" {
return values[1:], nil
}
return values, nil
}
return strings.Split(raw, ","), nil
}

View file

@ -1,60 +0,0 @@
package plugins
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_stringToSliceHookFunc(t *testing.T) {
testCases := []struct {
desc string
data string
expected []string
}{
{
desc: "without separator",
data: "abc",
expected: []string{"abc"},
},
{
desc: "with the file separator",
data: "a║b║c",
expected: []string{"a", "b", "c"},
},
{
desc: "with the label separator",
data: "a,b,c",
expected: []string{"a", "b", "c"},
},
{
desc: "with the file separator and values with commas",
data: "a,z║b,w║c,x,y",
expected: []string{"a,z", "b,w", "c,x,y"},
},
{
desc: "escaping workaround",
data: "║a,z",
expected: []string{"a,z"},
},
{
desc: "with the file separator and empty item",
data: "║a║z",
expected: []string{"", "a", "z"},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
values, err := stringToSliceHookFunc(reflect.String, reflect.Slice, test.data)
require.NoError(t, err)
assert.EqualValues(t, test.expected, values)
})
}
}

View file

@ -93,7 +93,7 @@ func newProvider(builder providerBuilder, config map[string]interface{}, provide
}
cfg := &mapstructure.DecoderConfig{
DecodeHook: stringToSliceHookFunc,
DecodeHook: mapstructure.StringToSliceHookFunc(","),
WeaklyTypedInput: true,
Result: vConfig.Interface(),
}

View file

@ -35,7 +35,6 @@ spec:
- secret-ca1
- secret-ca2
clientAuthType: VerifyClientCertIfGiven
preferServerCipherSuites: true
---
apiVersion: v1
kind: Secret

View file

@ -35,7 +35,6 @@ spec:
- secret-ca-default1
- secret-ca-default2
clientAuthType: VerifyClientCertIfGiven
preferServerCipherSuites: true
---
apiVersion: traefik.containo.us/v1alpha1

View file

@ -35,7 +35,6 @@ spec:
- secret-ca1
- secret-ca2
clientAuthType: VerifyClientCertIfGiven
preferServerCipherSuites: true
---
apiVersion: traefik.containo.us/v1alpha1

View file

@ -35,7 +35,6 @@ spec:
- secret-ca1
- secret-ca2
clientAuthType: VerifyClientCertIfGiven
preferServerCipherSuites: true
---
apiVersion: traefik.containo.us/v1alpha1

View file

@ -45,14 +45,14 @@ var localSchemeBuilder = runtime.SchemeBuilder{
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
// of clientsets, like in:
//
// import (
// "k8s.io/client-go/kubernetes"
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
// )
// import (
// "k8s.io/client-go/kubernetes"
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
// )
//
// kclientset, _ := kubernetes.NewForConfig(c)
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
// kclientset, _ := kubernetes.NewForConfig(c)
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
//
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
// correctly.

View file

@ -45,14 +45,14 @@ var localSchemeBuilder = runtime.SchemeBuilder{
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
// of clientsets, like in:
//
// import (
// "k8s.io/client-go/kubernetes"
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
// )
// import (
// "k8s.io/client-go/kubernetes"
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
// )
//
// kclientset, _ := kubernetes.NewForConfig(c)
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
// kclientset, _ := kubernetes.NewForConfig(c)
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
//
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
// correctly.

View file

@ -881,9 +881,8 @@ func buildTLSOptions(ctx context.Context, client Client) map[string]tls.Options
CAFiles: clientCAs,
ClientAuthType: tlsOption.Spec.ClientAuth.ClientAuthType,
},
SniStrict: tlsOption.Spec.SniStrict,
PreferServerCipherSuites: tlsOption.Spec.PreferServerCipherSuites,
ALPNProtocols: alpnProtocols,
SniStrict: tlsOption.Spec.SniStrict,
ALPNProtocols: alpnProtocols,
}
}

View file

@ -666,8 +666,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
},
ClientAuthType: "VerifyClientCertIfGiven",
},
SniStrict: true,
PreferServerCipherSuites: true,
SniStrict: true,
ALPNProtocols: []string{
"h2",
"http/1.1",
@ -2748,8 +2747,7 @@ func TestLoadIngressRoutes(t *testing.T) {
},
ClientAuthType: "VerifyClientCertIfGiven",
},
SniStrict: true,
PreferServerCipherSuites: true,
SniStrict: true,
ALPNProtocols: []string{
"h2",
"http/1.1",
@ -2862,8 +2860,7 @@ func TestLoadIngressRoutes(t *testing.T) {
},
ClientAuthType: "VerifyClientCertIfGiven",
},
SniStrict: true,
PreferServerCipherSuites: true,
SniStrict: true,
ALPNProtocols: []string{
"h2",
"http/1.1",

View file

@ -42,7 +42,8 @@ type TLSOptionSpec struct {
// SniStrict defines whether Traefik allows connections from clients connections that do not specify a server_name extension.
SniStrict bool `json:"sniStrict,omitempty"`
// PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
// It is enabled automatically when minVersion or maxVersion are set.
// It is enabled automatically when minVersion or maxVersion is set.
// Deprecated: https://github.com/golang/go/issues/45430
PreferServerCipherSuites bool `json:"preferServerCipherSuites,omitempty"`
// ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference.
// More info: https://doc.traefik.io/traefik/v2.8/https/tls/#alpn-protocols

View file

@ -304,7 +304,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
serviceName := provider.Normalize(ingress.Namespace + "-" + pa.Backend.Service.Name + "-" + portString)
conf.HTTP.Services[serviceName] = service
routerKey := strings.TrimPrefix(provider.Normalize(ingress.Name+"-"+ingress.Namespace+"-"+rule.Host+pa.Path), "-")
routerKey := strings.TrimPrefix(provider.Normalize(ingress.Namespace+"-"+ingress.Name+"-"+rule.Host+pa.Path), "-")
routers[routerKey] = append(routers[routerKey], loadRouter(rule, pa, rtConfig, serviceName))
}
}

View file

@ -1696,7 +1696,7 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{
"example-com-testing-bar": {
"testing-example-com-bar": {
Rule: "PathPrefix(`/bar`)",
Service: "testing-service-bar-8080",
},
@ -1724,7 +1724,7 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{
"example-com-testing-foo": {
"testing-example-com-foo": {
Rule: "PathPrefix(`/foo`)",
Service: "testing-service-foo-8080",
},

View file

@ -67,7 +67,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
logger := log.FromContext(ctx)
operation := func() error {
if _, err := p.kvClient.Exists(path.Join(p.RootKey, "qmslkjdfmqlskdjfmqlksjazçueznbvbwzlkajzebvkwjdcqmlsfj"), nil); err != nil {
if _, err := p.kvClient.Exists(ctx, path.Join(p.RootKey, "qmslkjdfmqlskdjfmqlksjazçueznbvbwzlkajzebvkwjdcqmlsfj"), nil); err != nil {
return fmt.Errorf("KV store connection error: %w", err)
}
return nil
@ -76,12 +76,12 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
notify := func(err error, time time.Duration) {
logger.Errorf("KV connection error: %+v, retrying in %s", err, time)
}
err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctx), notify)
if err != nil {
return fmt.Errorf("cannot connect to KV server: %w", err)
}
configuration, err := p.buildConfiguration()
configuration, err := p.buildConfiguration(ctx)
if err != nil {
logger.Errorf("Cannot build the configuration: %v", err)
} else {
@ -105,7 +105,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
func (p *Provider) watchKv(ctx context.Context, configurationChan chan<- dynamic.Message) error {
operation := func() error {
events, err := p.kvClient.WatchTree(p.RootKey, ctx.Done(), nil)
events, err := p.kvClient.WatchTree(ctx, p.RootKey, nil)
if err != nil {
return fmt.Errorf("failed to watch KV: %w", err)
}
@ -119,7 +119,7 @@ func (p *Provider) watchKv(ctx context.Context, configurationChan chan<- dynamic
return errors.New("the WatchTree channel is closed")
}
configuration, errC := p.buildConfiguration()
configuration, errC := p.buildConfiguration(ctx)
if errC != nil {
return errC
}
@ -146,8 +146,8 @@ func (p *Provider) watchKv(ctx context.Context, configurationChan chan<- dynamic
return nil
}
func (p *Provider) buildConfiguration() (*dynamic.Configuration, error) {
pairs, err := p.kvClient.List(p.RootKey, nil)
func (p *Provider) buildConfiguration(ctx context.Context) (*dynamic.Configuration, error) {
pairs, err := p.kvClient.List(ctx, p.RootKey, nil)
if err != nil {
return nil, err
}
@ -190,7 +190,7 @@ func (p *Provider) createKVClient(ctx context.Context) (store.Store, error) {
redis.Register()
}
kvStore, err := valkeyrie.NewStore(p.storeType, p.Endpoints, storeConfig)
kvStore, err := valkeyrie.NewStore(ctx, p.storeType, p.Endpoints, storeConfig)
if err != nil {
return nil, err
}

View file

@ -1,6 +1,7 @@
package kv
import (
"context"
"errors"
"strings"
@ -41,11 +42,11 @@ func newKvClientMock(kvPairs []*store.KVPair, err error) *Mock {
return mock
}
func (s *Mock) Put(key string, value []byte, opts *store.WriteOptions) error {
func (s *Mock) Put(ctx context.Context, key string, value []byte, opts *store.WriteOptions) error {
return errors.New("method Put not supported")
}
func (s *Mock) Get(key string, options *store.ReadOptions) (*store.KVPair, error) {
func (s *Mock) Get(ctx context.Context, key string, options *store.ReadOptions) (*store.KVPair, error) {
if err := s.Error.Get; err != nil {
return nil, err
}
@ -57,12 +58,12 @@ func (s *Mock) Get(key string, options *store.ReadOptions) (*store.KVPair, error
return nil, store.ErrKeyNotFound
}
func (s *Mock) Delete(key string) error {
func (s *Mock) Delete(ctx context.Context, key string) error {
return errors.New("method Delete not supported")
}
// Exists mock.
func (s *Mock) Exists(key string, options *store.ReadOptions) (bool, error) {
func (s *Mock) Exists(ctx context.Context, key string, options *store.ReadOptions) (bool, error) {
if err := s.Error.Get; err != nil {
return false, err
}
@ -75,22 +76,22 @@ func (s *Mock) Exists(key string, options *store.ReadOptions) (bool, error) {
}
// Watch mock.
func (s *Mock) Watch(key string, stopCh <-chan struct{}, options *store.ReadOptions) (<-chan *store.KVPair, error) {
func (s *Mock) Watch(ctx context.Context, key string, options *store.ReadOptions) (<-chan *store.KVPair, error) {
return nil, errors.New("method Watch not supported")
}
// WatchTree mock.
func (s *Mock) WatchTree(prefix string, stopCh <-chan struct{}, options *store.ReadOptions) (<-chan []*store.KVPair, error) {
func (s *Mock) WatchTree(ctx context.Context, prefix string, options *store.ReadOptions) (<-chan []*store.KVPair, error) {
return s.WatchTreeMethod(), nil
}
// NewLock mock.
func (s *Mock) NewLock(key string, options *store.LockOptions) (store.Locker, error) {
func (s *Mock) NewLock(ctx context.Context, key string, options *store.LockOptions) (store.Locker, error) {
return nil, errors.New("method NewLock not supported")
}
// List mock.
func (s *Mock) List(prefix string, options *store.ReadOptions) ([]*store.KVPair, error) {
func (s *Mock) List(ctx context.Context, prefix string, options *store.ReadOptions) ([]*store.KVPair, error) {
if err := s.Error.List; err != nil {
return nil, err
}
@ -104,19 +105,21 @@ func (s *Mock) List(prefix string, options *store.ReadOptions) ([]*store.KVPair,
}
// DeleteTree mock.
func (s *Mock) DeleteTree(prefix string) error {
func (s *Mock) DeleteTree(ctx context.Context, prefix string) error {
return errors.New("method DeleteTree not supported")
}
// AtomicPut mock.
func (s *Mock) AtomicPut(key string, value []byte, previous *store.KVPair, opts *store.WriteOptions) (bool, *store.KVPair, error) {
func (s *Mock) AtomicPut(ctx context.Context, key string, value []byte, previous *store.KVPair, opts *store.WriteOptions) (bool, *store.KVPair, error) {
return false, nil, errors.New("method AtomicPut not supported")
}
// AtomicDelete mock.
func (s *Mock) AtomicDelete(key string, previous *store.KVPair) (bool, error) {
func (s *Mock) AtomicDelete(ctx context.Context, key string, previous *store.KVPair) (bool, error) {
return false, errors.New("method AtomicDelete not supported")
}
// Close mock.
func (s *Mock) Close() {}
func (s *Mock) Close() error {
return nil
}

View file

@ -283,7 +283,7 @@ func Test_buildConfiguration(t *testing.T) {
"traefik/tls/certificates/1/stores/1": "foobar",
}))
cfg, err := provider.buildConfiguration()
cfg, err := provider.buildConfiguration(context.Background())
require.NoError(t, err)
expected := &dynamic.Configuration{
@ -929,7 +929,7 @@ func Test_buildConfiguration_KV_error(t *testing.T) {
},
}
cfg, err := provider.buildConfiguration()
cfg, err := provider.buildConfiguration(context.Background())
require.Error(t, err)
assert.Nil(t, cfg)
}

View file

@ -1,6 +1,8 @@
package kv
import (
"context"
"github.com/kvtools/valkeyrie/store"
"github.com/traefik/traefik/v2/pkg/log"
)
@ -9,110 +11,110 @@ type storeWrapper struct {
store.Store
}
func (s *storeWrapper) Put(key string, value []byte, options *store.WriteOptions) error {
func (s *storeWrapper) Put(ctx context.Context, key string, value []byte, options *store.WriteOptions) error {
log.WithoutContext().Debugf("Put: %s", key, string(value))
if s.Store == nil {
return nil
}
return s.Store.Put(key, value, options)
return s.Store.Put(ctx, key, value, options)
}
func (s *storeWrapper) Get(key string, options *store.ReadOptions) (*store.KVPair, error) {
func (s *storeWrapper) Get(ctx context.Context, key string, options *store.ReadOptions) (*store.KVPair, error) {
log.WithoutContext().Debugf("Get: %s", key)
if s.Store == nil {
return nil, nil
}
return s.Store.Get(key, options)
return s.Store.Get(ctx, key, options)
}
func (s *storeWrapper) Delete(key string) error {
func (s *storeWrapper) Delete(ctx context.Context, key string) error {
log.WithoutContext().Debugf("Delete: %s", key)
if s.Store == nil {
return nil
}
return s.Store.Delete(key)
return s.Store.Delete(ctx, key)
}
func (s *storeWrapper) Exists(key string, options *store.ReadOptions) (bool, error) {
func (s *storeWrapper) Exists(ctx context.Context, key string, options *store.ReadOptions) (bool, error) {
log.WithoutContext().Debugf("Exists: %s", key)
if s.Store == nil {
return true, nil
}
return s.Store.Exists(key, options)
return s.Store.Exists(ctx, key, options)
}
func (s *storeWrapper) Watch(key string, stopCh <-chan struct{}, options *store.ReadOptions) (<-chan *store.KVPair, error) {
func (s *storeWrapper) Watch(ctx context.Context, key string, options *store.ReadOptions) (<-chan *store.KVPair, error) {
log.WithoutContext().Debugf("Watch: %s", key)
if s.Store == nil {
return nil, nil
}
return s.Store.Watch(key, stopCh, options)
return s.Store.Watch(ctx, key, options)
}
func (s *storeWrapper) WatchTree(directory string, stopCh <-chan struct{}, options *store.ReadOptions) (<-chan []*store.KVPair, error) {
func (s *storeWrapper) WatchTree(ctx context.Context, directory string, options *store.ReadOptions) (<-chan []*store.KVPair, error) {
log.WithoutContext().Debugf("WatchTree: %s", directory)
if s.Store == nil {
return nil, nil
}
return s.Store.WatchTree(directory, stopCh, options)
return s.Store.WatchTree(ctx, directory, options)
}
func (s *storeWrapper) NewLock(key string, options *store.LockOptions) (store.Locker, error) {
func (s *storeWrapper) NewLock(ctx context.Context, key string, options *store.LockOptions) (store.Locker, error) {
log.WithoutContext().Debugf("NewLock: %s", key)
if s.Store == nil {
return nil, nil
}
return s.Store.NewLock(key, options)
return s.Store.NewLock(ctx, key, options)
}
func (s *storeWrapper) List(directory string, options *store.ReadOptions) ([]*store.KVPair, error) {
func (s *storeWrapper) List(ctx context.Context, directory string, options *store.ReadOptions) ([]*store.KVPair, error) {
log.WithoutContext().Debugf("List: %s", directory)
if s.Store == nil {
return nil, nil
}
return s.Store.List(directory, options)
return s.Store.List(ctx, directory, options)
}
func (s *storeWrapper) DeleteTree(directory string) error {
func (s *storeWrapper) DeleteTree(ctx context.Context, directory string) error {
log.WithoutContext().Debugf("DeleteTree: %s", directory)
if s.Store == nil {
return nil
}
return s.Store.DeleteTree(directory)
return s.Store.DeleteTree(ctx, directory)
}
func (s *storeWrapper) AtomicPut(key string, value []byte, previous *store.KVPair, options *store.WriteOptions) (bool, *store.KVPair, error) {
func (s *storeWrapper) AtomicPut(ctx context.Context, key string, value []byte, previous *store.KVPair, options *store.WriteOptions) (bool, *store.KVPair, error) {
log.WithoutContext().Debugf("AtomicPut: %s", key, string(value), previous)
if s.Store == nil {
return true, nil, nil
}
return s.Store.AtomicPut(key, value, previous, options)
return s.Store.AtomicPut(ctx, key, value, previous, options)
}
func (s *storeWrapper) AtomicDelete(key string, previous *store.KVPair) (bool, error) {
func (s *storeWrapper) AtomicDelete(ctx context.Context, key string, previous *store.KVPair) (bool, error) {
log.WithoutContext().Debugf("AtomicDelete: %s", key, previous)
if s.Store == nil {
return true, nil
}
return s.Store.AtomicDelete(key, previous)
return s.Store.AtomicDelete(ctx, key, previous)
}
func (s *storeWrapper) Close() {
func (s *storeWrapper) Close() error {
log.WithoutContext().Debugf("Close")
if s.Store == nil {
return
return nil
}
s.Store.Close()
return s.Store.Close()
}

View file

@ -192,7 +192,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
notify := func(err error, time time.Duration) {
logger.Errorf("Provider connection error %+v, retrying in %s", err, time)
}
err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctx), notify)
if err != nil {
logger.Errorf("Cannot connect to Provider server: %+v", err)
}

View file

@ -442,8 +442,7 @@ func init() {
CAFiles: []traefiktls.FileOrContent{"ca.pem"},
ClientAuthType: "RequireAndVerifyClientCert",
},
SniStrict: true,
PreferServerCipherSuites: true,
SniStrict: true,
},
},
Certificates: []*traefiktls.CertAndStores{

View file

@ -463,8 +463,7 @@
"foo"
],
"clientAuth": {},
"sniStrict": true,
"preferServerCipherSuites": true
"sniStrict": true
}
},
"stores": {

View file

@ -471,8 +471,7 @@
],
"clientAuthType": "RequireAndVerifyClientCert"
},
"sniStrict": true,
"preferServerCipherSuites": true
"sniStrict": true
}
},
"stores": {
@ -484,4 +483,4 @@
}
}
}
}
}

View file

@ -5,6 +5,8 @@ import (
"strings"
"github.com/vulcand/predicate"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
const (
@ -41,7 +43,7 @@ func NewParser(matchers []string) (predicate.Parser, error) {
parserFuncs[matcherName] = fn
parserFuncs[strings.ToLower(matcherName)] = fn
parserFuncs[strings.ToUpper(matcherName)] = fn
parserFuncs[strings.Title(strings.ToLower(matcherName))] = fn
parserFuncs[cases.Title(language.Und).String(strings.ToLower(matcherName))] = fn
}
return predicate.NewParser(predicate.Def{

View file

@ -827,7 +827,7 @@ func BenchmarkRouterServe(b *testing.B) {
b.Cleanup(func() { server.Close() })
res := &http.Response{
StatusCode: 200,
StatusCode: http.StatusOK,
Body: io.NopCloser(strings.NewReader("")),
}
@ -879,7 +879,7 @@ func BenchmarkRouterServe(b *testing.B) {
func BenchmarkService(b *testing.B) {
res := &http.Response{
StatusCode: 200,
StatusCode: http.StatusOK,
Body: io.NopCloser(strings.NewReader("")),
}

View file

@ -9,6 +9,7 @@ import (
"io"
"net"
"net/http"
"net/url"
"strings"
"testing"
"time"
@ -109,8 +110,13 @@ func Test_Routing(t *testing.T) {
for {
conn, err := tcpBackendListener.Accept()
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) && netErr.Temporary() {
var opErr *net.OpError
if errors.As(err, &opErr) && opErr.Temporary() {
continue
}
var urlErr *url.Error
if errors.As(err, &urlErr) && urlErr.Temporary() {
continue
}

View file

@ -7,6 +7,7 @@ import (
stdlog "log"
"net"
"net/http"
"net/url"
"os"
"strings"
"sync"
@ -195,8 +196,13 @@ func (e *TCPEntryPoint) Start(ctx context.Context) {
if err != nil {
logger.Error(err)
var netErr net.Error
if errors.As(err, &netErr) && netErr.Temporary() {
var opErr *net.OpError
if errors.As(err, &opErr) && opErr.Temporary() {
continue
}
var urlErr *url.Error
if errors.As(err, &urlErr) && urlErr.Temporary() {
continue
}

View file

@ -20,7 +20,7 @@ func (t *staticTransport) RoundTrip(r *http.Request) (*http.Response, error) {
func BenchmarkProxy(b *testing.B) {
res := &http.Response{
StatusCode: 200,
StatusCode: http.StatusOK,
Body: io.NopCloser(strings.NewReader("")),
}

View file

@ -456,7 +456,7 @@ func TestWebSocketUpgradeFailed(t *testing.T) {
mux := http.NewServeMux()
mux.HandleFunc("/ws", func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(400)
w.WriteHeader(http.StatusBadRequest)
})
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
mux.ServeHTTP(w, req)
@ -472,7 +472,7 @@ func TestWebSocketUpgradeFailed(t *testing.T) {
req.URL.Path = path
f.ServeHTTP(w, req)
} else {
w.WriteHeader(200)
w.WriteHeader(http.StatusOK)
}
}))
defer proxy.Close()

View file

@ -22,7 +22,7 @@ type Options struct {
CurvePreferences []string `json:"curvePreferences,omitempty" toml:"curvePreferences,omitempty" yaml:"curvePreferences,omitempty" export:"true"`
ClientAuth ClientAuth `json:"clientAuth,omitempty" toml:"clientAuth,omitempty" yaml:"clientAuth,omitempty"`
SniStrict bool `json:"sniStrict,omitempty" toml:"sniStrict,omitempty" yaml:"sniStrict,omitempty" export:"true"`
PreferServerCipherSuites bool `json:"preferServerCipherSuites,omitempty" toml:"preferServerCipherSuites,omitempty" yaml:"preferServerCipherSuites,omitempty" export:"true"`
PreferServerCipherSuites bool `json:"preferServerCipherSuites,omitempty" toml:"preferServerCipherSuites,omitempty" yaml:"preferServerCipherSuites,omitempty" export:"true"` // Deprecated: https://github.com/golang/go/issues/45430
ALPNProtocols []string `json:"alpnProtocols,omitempty" toml:"alpnProtocols,omitempty" yaml:"alpnProtocols,omitempty" export:"true"`
}

View file

@ -299,18 +299,13 @@ func buildTLSConfig(tlsOption Options) (*tls.Config, error) {
}
}
// Set PreferServerCipherSuites.
conf.PreferServerCipherSuites = tlsOption.PreferServerCipherSuites
// Set the minimum TLS version if set in the config
if minConst, exists := MinVersion[tlsOption.MinVersion]; exists {
conf.PreferServerCipherSuites = true
conf.MinVersion = minConst
}
// Set the maximum TLS version if set in the config TOML
if maxConst, exists := MaxVersion[tlsOption.MaxVersion]; exists {
conf.PreferServerCipherSuites = true
conf.MaxVersion = maxConst
}