Upgrade golangci-lint

This commit is contained in:
Michael
2026-01-14 17:26:08 +01:00
committed by GitHub
parent 9e5d4ba5a1
commit 51343bc15f
171 changed files with 1463 additions and 1416 deletions
+2 -2
View File
@@ -7,8 +7,8 @@ on:
env: env:
GO_VERSION: '1.24' GO_VERSION: '1.24'
GOLANGCI_LINT_VERSION: v2.0.2 GOLANGCI_LINT_VERSION: v2.7.2
MISSPELL_VERSION: v0.6.0 MISSPELL_VERSION: v0.7.0
jobs: jobs:
+20 -2
View File
@@ -36,6 +36,7 @@ linters:
- nilnil # Not relevant - nilnil # Not relevant
- nlreturn # Not relevant - nlreturn # Not relevant
- noctx # Too strict - noctx # Too strict
- noinlineerr # Too strict
- nonamedreturns # Too strict - nonamedreturns # Too strict
- paralleltest # Not relevant - paralleltest # Not relevant
- prealloc # Too many false-positive. - prealloc # Too many false-positive.
@@ -47,6 +48,7 @@ linters:
- varnamelen # Not relevant - varnamelen # Not relevant
- wrapcheck # Too strict - wrapcheck # Too strict
- wsl # Too strict - wsl # Too strict
- wsl_v5 # Too strict
settings: settings:
depguard: depguard:
@@ -292,15 +294,31 @@ linters:
source: 'errors.New\("Nomad provider' source: 'errors.New\("Nomad provider'
text: 'ST1005: error strings should not be capitalized' text: 'ST1005: error strings should not be capitalized'
- path: (.+)\.go - path: (.+)\.go
text: 'struct-tag: unknown option ''inline'' in JSON tag' text: 'omitzero: Omitempty has no effect on nested struct field'
linters:
- modernize
- path: (.+)\.go
text: 'struct-tag: unknown option "inline" in json tag'
linters: linters:
- revive - revive
- path: (.+)\.go - path: (.+)\.go
text: 'struct-tag: unknown option ''omitzero'' in TOML tag' text: 'struct-tag: unknown option "omitzero" in toml tag'
linters:
- revive
- path: (pkg/types/.+|pkg/api/.+)\.go
text: 'var-naming: avoid meaningless package names'
linters:
- revive
- path: (pkg/muxer/http/.+|pkg/provider/http/.+)\.go
text: 'var-naming: avoid package names that conflict with Go standard library package names'
linters: linters:
- revive - revive
- path: (.+)\.go$ - path: (.+)\.go$
text: 'SA1019: http.CloseNotifier has been deprecated' # FIXME must be fixed text: 'SA1019: http.CloseNotifier has been deprecated' # FIXME must be fixed
- path: (.+)\.go$
text: 'SA1019: dynamic.(TCPIPWhiteList|IPWhiteList) is deprecated: please use IPAllowList instead.'
- path: (.+)\.go$
text: 'SA1019: middlewareTCP.Spec.IPWhiteList is deprecated: please use IPAllowList instead.'
- path: (.+)\.go$ - path: (.+)\.go$
text: 'SA1019: cfg.(SSLRedirect|SSLTemporaryRedirect|SSLHost|SSLForceHost|FeaturePolicy) is deprecated' text: 'SA1019: cfg.(SSLRedirect|SSLTemporaryRedirect|SSLHost|SSLForceHost|FeaturePolicy) is deprecated'
- path: (.+)\.go$ - path: (.+)\.go$
+1
View File
@@ -10,6 +10,7 @@ import (
// TraefikCmdConfiguration wraps the static configuration and extra parameters. // TraefikCmdConfiguration wraps the static configuration and extra parameters.
type TraefikCmdConfiguration struct { type TraefikCmdConfiguration struct {
static.Configuration `export:"true"` static.Configuration `export:"true"`
// ConfigFile is the path to the configuration file. // ConfigFile is the path to the configuration file.
ConfigFile string `description:"Configuration file to use. If specified all other flags are ignored." export:"true"` ConfigFile string `description:"Configuration file to use. If specified all other flags are ignored." export:"true"`
} }
+1 -1
View File
@@ -83,7 +83,7 @@ func run(dest string) error {
return err return err
} }
return os.WriteFile(filepath.Join(dest, "marshaler.go"), []byte(fmt.Sprintf(marsh, destPkg)), 0o666) return os.WriteFile(filepath.Join(dest, "marshaler.go"), fmt.Appendf(nil, marsh, destPkg), 0o666)
} }
func cleanType(typ types.Type, base string) string { func cleanType(typ types.Type, base string) string {
@@ -1273,6 +1273,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration. IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP. This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead. Deprecated: please use IPAllowList instead.
properties: properties:
ipStrategy: ipStrategy:
@@ -1663,8 +1664,9 @@ spec:
description: |- description: |-
IPWhiteList defines the IPWhiteList middleware configuration. IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP. This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties: properties:
sourceRange: sourceRange:
description: SourceRange defines the allowed IPs (or ranges of description: SourceRange defines the allowed IPs (or ranges of
@@ -1907,6 +1909,7 @@ spec:
description: |- description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's. 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 is set. It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430 Deprecated: https://github.com/golang/go/issues/45430
type: boolean type: boolean
sniStrict: sniStrict:
@@ -3703,6 +3706,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration. IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP. This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead. Deprecated: please use IPAllowList instead.
properties: properties:
ipStrategy: ipStrategy:
@@ -4093,8 +4097,9 @@ spec:
description: |- description: |-
IPWhiteList defines the IPWhiteList middleware configuration. IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP. This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties: properties:
sourceRange: sourceRange:
description: SourceRange defines the allowed IPs (or ranges of description: SourceRange defines the allowed IPs (or ranges of
@@ -4337,6 +4342,7 @@ spec:
description: |- description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's. 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 is set. It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430 Deprecated: https://github.com/golang/go/issues/45430
type: boolean type: boolean
sniStrict: sniStrict:
@@ -658,6 +658,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration. IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP. This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead. Deprecated: please use IPAllowList instead.
properties: properties:
ipStrategy: ipStrategy:
@@ -68,8 +68,9 @@ spec:
description: |- description: |-
IPWhiteList defines the IPWhiteList middleware configuration. IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP. This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties: properties:
sourceRange: sourceRange:
description: SourceRange defines the allowed IPs (or ranges of description: SourceRange defines the allowed IPs (or ranges of
@@ -99,6 +99,7 @@ spec:
description: |- description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's. 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 is set. It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430 Deprecated: https://github.com/golang/go/issues/45430
type: boolean type: boolean
sniStrict: sniStrict:
@@ -658,6 +658,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration. IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP. This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead. Deprecated: please use IPAllowList instead.
properties: properties:
ipStrategy: ipStrategy:
@@ -68,8 +68,9 @@ spec:
description: |- description: |-
IPWhiteList defines the IPWhiteList middleware configuration. IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP. This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties: properties:
sourceRange: sourceRange:
description: SourceRange defines the allowed IPs (or ranges of description: SourceRange defines the allowed IPs (or ranges of
@@ -99,6 +99,7 @@ spec:
description: |- description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's. 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 is set. It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430 Deprecated: https://github.com/golang/go/issues/45430
type: boolean type: boolean
sniStrict: sniStrict:
+1 -1
View File
@@ -28,7 +28,7 @@ theme:
prev: 'Previous' prev: 'Previous'
next: 'Next' next: 'Next'
copyright: 'Traefik Labs • Copyright © 2016-2025' copyright: 'Traefik Labs • Copyright © 2016-2026'
extra_javascript: extra_javascript:
- assets/js/hljs/highlight.pack.js # Download from https://highlightjs.org/download/ and enable YAML, TOML and Dockerfile - assets/js/hljs/highlight.pack.js # Download from https://highlightjs.org/download/ and enable YAML, TOML and Dockerfile
+1 -2
View File
@@ -245,8 +245,7 @@ func digestParts(resp *http.Response) map[string]string {
result := map[string]string{} result := map[string]string{}
if len(resp.Header["Www-Authenticate"]) > 0 { if len(resp.Header["Www-Authenticate"]) > 0 {
wantedHeaders := []string{"nonce", "realm", "qop", "opaque"} wantedHeaders := []string{"nonce", "realm", "qop", "opaque"}
responseHeaders := strings.Split(resp.Header["Www-Authenticate"][0], ",") for r := range strings.SplitSeq(resp.Header["Www-Authenticate"][0], ",") {
for _, r := range responseHeaders {
for _, w := range wantedHeaders { for _, w := range wantedHeaders {
if strings.Contains(r, w) { if strings.Contains(r, w) {
result[w] = strings.Split(r, `"`)[1] result[w] = strings.Split(r, `"`)[1]
+6 -5
View File
@@ -27,6 +27,7 @@ import (
// ACME test suites. // ACME test suites.
type AcmeSuite struct { type AcmeSuite struct {
BaseSuite BaseSuite
pebbleIP string pebbleIP string
fakeDNSServer *dns.Server fakeDNSServer *dns.Server
} }
@@ -63,11 +64,6 @@ const (
wildcardDomain = "*.acme.wtf" wildcardDomain = "*.acme.wtf"
) )
func (s *AcmeSuite) getAcmeURL() string {
return fmt.Sprintf("https://%s/dir",
net.JoinHostPort(s.pebbleIP, "14000"))
}
func setupPebbleRootCA() (*http.Transport, error) { func setupPebbleRootCA() (*http.Transport, error) {
path, err := filepath.Abs("fixtures/acme/ssl/pebble.minica.pem") path, err := filepath.Abs("fixtures/acme/ssl/pebble.minica.pem")
if err != nil { if err != nil {
@@ -540,3 +536,8 @@ func (s *AcmeSuite) retrieveAcmeCertificate(testCase acmeTestCase) {
assert.Equal(s.T(), sub.expectedAlgorithm, gotPublicKeyAlgorithm) assert.Equal(s.T(), sub.expectedAlgorithm, gotPublicKeyAlgorithm)
} }
} }
func (s *AcmeSuite) getAcmeURL() string {
return fmt.Sprintf("https://%s/dir",
net.JoinHostPort(s.pebbleIP, "14000"))
}
+42 -41
View File
@@ -16,6 +16,7 @@ import (
type ConsulCatalogSuite struct { type ConsulCatalogSuite struct {
BaseSuite BaseSuite
consulClient *api.Client consulClient *api.Client
consulAgentClient *api.Client consulAgentClient *api.Client
consulURL string consulURL string
@@ -53,47 +54,6 @@ func (s *ConsulCatalogSuite) TearDownSuite() {
s.BaseSuite.TearDownSuite() s.BaseSuite.TearDownSuite()
} }
func (s *ConsulCatalogSuite) waitToElectConsulLeader() error {
return try.Do(15*time.Second, func() error {
leader, err := s.consulClient.Status().Leader()
if err != nil || len(leader) == 0 {
return fmt.Errorf("leader not found. %w", err)
}
return nil
})
}
func (s *ConsulCatalogSuite) waitForConnectCA() error {
return try.Do(15*time.Second, func() error {
caroots, _, err := s.consulClient.Connect().CARoots(nil)
if err != nil || len(caroots.Roots) == 0 {
return fmt.Errorf("connect CA not fully initialized. %w", err)
}
return nil
})
}
func (s *ConsulCatalogSuite) registerService(reg *api.AgentServiceRegistration, onAgent bool) error {
client := s.consulClient
if onAgent {
client = s.consulAgentClient
}
return client.Agent().ServiceRegister(reg)
}
func (s *ConsulCatalogSuite) deregisterService(id string, onAgent bool) error {
client := s.consulClient
if onAgent {
client = s.consulAgentClient
}
return client.Agent().ServiceDeregister(id)
}
func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings() { func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings() {
reg1 := &api.AgentServiceRegistration{ reg1 := &api.AgentServiceRegistration{
ID: "whoami1", ID: "whoami1",
@@ -847,3 +807,44 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware() {
err = s.deregisterService("whoami1", false) err = s.deregisterService("whoami1", false)
require.NoError(s.T(), err) require.NoError(s.T(), err)
} }
func (s *ConsulCatalogSuite) waitToElectConsulLeader() error {
return try.Do(15*time.Second, func() error {
leader, err := s.consulClient.Status().Leader()
if err != nil || len(leader) == 0 {
return fmt.Errorf("leader not found. %w", err)
}
return nil
})
}
func (s *ConsulCatalogSuite) waitForConnectCA() error {
return try.Do(15*time.Second, func() error {
caroots, _, err := s.consulClient.Connect().CARoots(nil)
if err != nil || len(caroots.Roots) == 0 {
return fmt.Errorf("connect CA not fully initialized. %w", err)
}
return nil
})
}
func (s *ConsulCatalogSuite) registerService(reg *api.AgentServiceRegistration, onAgent bool) error {
client := s.consulClient
if onAgent {
client = s.consulAgentClient
}
return client.Agent().ServiceRegister(reg)
}
func (s *ConsulCatalogSuite) deregisterService(id string, onAgent bool) error {
client := s.consulClient
if onAgent {
client = s.consulAgentClient
}
return client.Agent().ServiceDeregister(id)
}
+11 -10
View File
@@ -26,6 +26,7 @@ import (
// Consul test suites. // Consul test suites.
type ConsulSuite struct { type ConsulSuite struct {
BaseSuite BaseSuite
kvClient store.Store kvClient store.Store
consulURL string consulURL string
} }
@@ -164,16 +165,6 @@ func (s *ConsulSuite) TestSimpleConfiguration() {
} }
} }
func (s *ConsulSuite) assertWhoami(host string, expectedStatusCode int) {
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
require.NoError(s.T(), err)
req.Host = host
resp, err := try.ResponseUntilStatusCode(req, 15*time.Second, expectedStatusCode)
require.NoError(s.T(), err)
resp.Body.Close()
}
func (s *ConsulSuite) TestDeleteRootKey() { func (s *ConsulSuite) TestDeleteRootKey() {
// This test case reproduce the issue: https://github.com/traefik/traefik/issues/8092 // This test case reproduce the issue: https://github.com/traefik/traefik/issues/8092
@@ -222,3 +213,13 @@ func (s *ConsulSuite) TestDeleteRootKey() {
s.assertWhoami("kv1.localhost", http.StatusNotFound) s.assertWhoami("kv1.localhost", http.StatusNotFound)
s.assertWhoami("kv2.localhost", http.StatusNotFound) s.assertWhoami("kv2.localhost", http.StatusNotFound)
} }
func (s *ConsulSuite) assertWhoami(host string, expectedStatusCode int) {
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
require.NoError(s.T(), err)
req.Host = host
resp, err := try.ResponseUntilStatusCode(req, 15*time.Second, expectedStatusCode)
require.NoError(s.T(), err)
resp.Body.Close()
}
+3 -3
View File
@@ -81,7 +81,7 @@ func (s *DockerSuite) TestDefaultDockerContainers() {
body, err := io.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
require.NoError(s.T(), err) require.NoError(s.T(), err)
var version map[string]interface{} var version map[string]any
assert.NoError(s.T(), json.Unmarshal(body, &version)) assert.NoError(s.T(), json.Unmarshal(body, &version))
assert.Equal(s.T(), "swarm/1.0.0", version["Version"]) assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
@@ -145,7 +145,7 @@ func (s *DockerSuite) TestDockerContainersWithLabels() {
body, err := io.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
require.NoError(s.T(), err) require.NoError(s.T(), err)
var version map[string]interface{} var version map[string]any
assert.NoError(s.T(), json.Unmarshal(body, &version)) assert.NoError(s.T(), json.Unmarshal(body, &version))
assert.Equal(s.T(), "swarm/1.0.0", version["Version"]) assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
@@ -203,7 +203,7 @@ func (s *DockerSuite) TestRestartDockerContainers() {
body, err := io.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
require.NoError(s.T(), err) require.NoError(s.T(), err)
var version map[string]interface{} var version map[string]any
assert.NoError(s.T(), json.Unmarshal(body, &version)) assert.NoError(s.T(), json.Unmarshal(body, &version))
assert.Equal(s.T(), "swarm/1.0.0", version["Version"]) assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
+1
View File
@@ -14,6 +14,7 @@ import (
// ErrorPagesSuite test suites. // ErrorPagesSuite test suites.
type ErrorPagesSuite struct { type ErrorPagesSuite struct {
BaseSuite BaseSuite
ErrorPageIP string ErrorPageIP string
BackendIP string BackendIP string
} }
+1
View File
@@ -24,6 +24,7 @@ import (
// etcd test suites. // etcd test suites.
type EtcdSuite struct { type EtcdSuite struct {
BaseSuite BaseSuite
kvClient store.Store kvClient store.Store
etcdAddr string etcdAddr string
} }
+8 -2
View File
@@ -1273,6 +1273,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration. IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP. This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead. Deprecated: please use IPAllowList instead.
properties: properties:
ipStrategy: ipStrategy:
@@ -1663,8 +1664,9 @@ spec:
description: |- description: |-
IPWhiteList defines the IPWhiteList middleware configuration. IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP. This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties: properties:
sourceRange: sourceRange:
description: SourceRange defines the allowed IPs (or ranges of description: SourceRange defines the allowed IPs (or ranges of
@@ -1907,6 +1909,7 @@ spec:
description: |- description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's. 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 is set. It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430 Deprecated: https://github.com/golang/go/issues/45430
type: boolean type: boolean
sniStrict: sniStrict:
@@ -3703,6 +3706,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration. IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP. This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead. Deprecated: please use IPAllowList instead.
properties: properties:
ipStrategy: ipStrategy:
@@ -4093,8 +4097,9 @@ spec:
description: |- description: |-
IPWhiteList defines the IPWhiteList middleware configuration. IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP. This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/ More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties: properties:
sourceRange: sourceRange:
description: SourceRange defines the allowed IPs (or ranges of description: SourceRange defines the allowed IPs (or ranges of
@@ -4337,6 +4342,7 @@ spec:
description: |- description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's. 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 is set. It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430 Deprecated: https://github.com/golang/go/issues/45430
type: boolean type: boolean
sniStrict: sniStrict:
+4 -3
View File
@@ -19,6 +19,7 @@ import (
// HealthCheck test suites. // HealthCheck test suites.
type HealthCheckSuite struct { type HealthCheckSuite struct {
BaseSuite BaseSuite
whoami1IP string whoami1IP string
whoami2IP string whoami2IP string
whoami3IP string whoami3IP string
@@ -305,7 +306,7 @@ func (s *HealthCheckSuite) TestPropagate() {
require.NoError(s.T(), err) require.NoError(s.T(), err)
} }
try.Sleep(time.Second) try.Sleep(time.Second) //nolint:staticcheck // Intentional use for integration test timing.
want2 := `IP: ` + s.whoami2IP want2 := `IP: ` + s.whoami2IP
want4 := `IP: ` + s.whoami4IP want4 := `IP: ` + s.whoami4IP
@@ -387,7 +388,7 @@ func (s *HealthCheckSuite) TestPropagate() {
require.NoError(s.T(), err) require.NoError(s.T(), err)
} }
try.Sleep(time.Second) try.Sleep(time.Second) //nolint:staticcheck // Intentional use for integration test timing.
// Verify that everything is down, and that we get 503s everywhere. // Verify that everything is down, and that we get 503s everywhere.
for range 2 { for range 2 {
@@ -413,7 +414,7 @@ func (s *HealthCheckSuite) TestPropagate() {
require.NoError(s.T(), err) require.NoError(s.T(), err)
} }
try.Sleep(time.Second) try.Sleep(time.Second) //nolint:staticcheck // Intentional use for integration test timing.
// Verify everything is up on root router. // Verify everything is up on root router.
reachedServers = make(map[string]int) reachedServers = make(map[string]int)
+3 -3
View File
@@ -187,7 +187,7 @@ func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {
s.RegisterService(&_Greeter_serviceDesc, srv) s.RegisterService(&_Greeter_serviceDesc, srv)
} }
func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _Greeter_SayHello_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(HelloRequest) in := new(HelloRequest)
if err := dec(in); err != nil { if err := dec(in); err != nil {
return nil, err return nil, err
@@ -199,13 +199,13 @@ func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(in
Server: srv, Server: srv,
FullMethod: "/helloworld.Greeter/SayHello", FullMethod: "/helloworld.Greeter/SayHello",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req any) (any, error) {
return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest))
} }
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Greeter_StreamExample_Handler(srv interface{}, stream grpc.ServerStream) error { func _Greeter_StreamExample_Handler(srv any, stream grpc.ServerStream) error {
m := new(StreamExampleRequest) m := new(StreamExampleRequest)
if err := stream.RecvMsg(m); err != nil { if err := stream.RecvMsg(m); err != nil {
return err return err
+34 -34
View File
@@ -876,40 +876,6 @@ func (s *HTTPSSuite) TestWithSNIDynamicConfigRouteWithTlsConfigurationDeletion()
require.NoError(s.T(), err) require.NoError(s.T(), err)
} }
// modifyCertificateConfFileContent replaces the content of a HTTPS configuration file.
func (s *HTTPSSuite) modifyCertificateConfFileContent(certFileName, confFileName string) {
file, err := os.OpenFile("./"+confFileName, os.O_WRONLY, os.ModeExclusive)
require.NoError(s.T(), err)
defer func() {
file.Close()
}()
err = file.Truncate(0)
require.NoError(s.T(), err)
// If certificate file is not provided, just truncate the configuration file
if len(certFileName) > 0 {
tlsConf := dynamic.Configuration{
TLS: &dynamic.TLSConfiguration{
Certificates: []*traefiktls.CertAndStores{
{
Certificate: traefiktls.Certificate{
CertFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".cert"),
KeyFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".key"),
},
},
},
},
}
var confBuffer bytes.Buffer
err := toml.NewEncoder(&confBuffer).Encode(tlsConf)
require.NoError(s.T(), err)
_, err = file.Write(confBuffer.Bytes())
require.NoError(s.T(), err)
}
}
func (s *HTTPSSuite) TestEntryPointHttpsRedirectAndPathModification() { func (s *HTTPSSuite) TestEntryPointHttpsRedirectAndPathModification() {
file := s.adaptFile("fixtures/https/https_redirect.toml", struct{}{}) file := s.adaptFile("fixtures/https/https_redirect.toml", struct{}{})
s.traefikCmd(withConfigFile(file)) s.traefikCmd(withConfigFile(file))
@@ -1176,6 +1142,40 @@ func (s *HTTPSSuite) TestWithInvalidTLSOption() {
} }
} }
// modifyCertificateConfFileContent replaces the content of a HTTPS configuration file.
func (s *HTTPSSuite) modifyCertificateConfFileContent(certFileName, confFileName string) {
file, err := os.OpenFile("./"+confFileName, os.O_WRONLY, os.ModeExclusive)
require.NoError(s.T(), err)
defer func() {
file.Close()
}()
err = file.Truncate(0)
require.NoError(s.T(), err)
// If certificate file is not provided, just truncate the configuration file
if len(certFileName) > 0 {
tlsConf := dynamic.Configuration{
TLS: &dynamic.TLSConfiguration{
Certificates: []*traefiktls.CertAndStores{
{
Certificate: traefiktls.Certificate{
CertFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".cert"),
KeyFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".key"),
},
},
},
},
}
var confBuffer bytes.Buffer
err := toml.NewEncoder(&confBuffer).Encode(tlsConf)
require.NoError(s.T(), err)
_, err = file.Write(confBuffer.Bytes())
require.NoError(s.T(), err)
}
}
func (s *SimpleSuite) TestMaxConcurrentStream() { func (s *SimpleSuite) TestMaxConcurrentStream() {
file := s.adaptFile("fixtures/https/max_concurrent_stream.toml", struct{}{}) file := s.adaptFile("fixtures/https/max_concurrent_stream.toml", struct{}{})
+37 -36
View File
@@ -61,45 +61,12 @@ type composeDeploy struct {
type BaseSuite struct { type BaseSuite struct {
suite.Suite suite.Suite
containers map[string]testcontainers.Container containers map[string]testcontainers.Container
network *testcontainers.DockerNetwork network *testcontainers.DockerNetwork
hostIP string hostIP string
} }
func (s *BaseSuite) waitForTraefik(containerName string) {
time.Sleep(1 * time.Second)
// Wait for Traefik to turn ready.
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/rawdata", nil)
require.NoError(s.T(), err)
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains(containerName))
require.NoError(s.T(), err)
}
func (s *BaseSuite) displayTraefikLogFile(path string) {
if s.T().Failed() {
if _, err := os.Stat(path); !os.IsNotExist(err) {
content, errRead := os.ReadFile(path)
// TODO TestName
// fmt.Printf("%s: Traefik logs: \n", c.TestName())
fmt.Print("Traefik logs: \n")
if errRead == nil {
fmt.Println(string(content))
} else {
fmt.Println(errRead)
}
} else {
// fmt.Printf("%s: No Traefik logs.\n", c.TestName())
fmt.Print("No Traefik logs.\n")
}
errRemove := os.Remove(path)
if errRemove != nil {
fmt.Println(errRemove)
}
}
}
func (s *BaseSuite) SetupSuite() { func (s *BaseSuite) SetupSuite() {
if isDockerDesktop(context.Background(), s.T()) { if isDockerDesktop(context.Background(), s.T()) {
_, err := os.Stat(tailscaleSecretFilePath) _, err := os.Stat(tailscaleSecretFilePath)
@@ -400,7 +367,7 @@ func (s *BaseSuite) displayTraefikLog(output *bytes.Buffer) {
if output == nil || output.Len() == 0 { if output == nil || output.Len() == 0 {
log.WithoutContext().Info("No Traefik logs.") log.WithoutContext().Info("No Traefik logs.")
} else { } else {
for _, line := range strings.Split(output.String(), "\n") { for line := range strings.SplitSeq(output.String(), "\n") {
log.WithoutContext().Info(line) log.WithoutContext().Info(line)
} }
} }
@@ -416,7 +383,7 @@ func (s *BaseSuite) getDockerHost() string {
return dockerHost return dockerHost
} }
func (s *BaseSuite) adaptFile(path string, tempObjects interface{}) string { func (s *BaseSuite) adaptFile(path string, tempObjects any) string {
// Load file // Load file
tmpl, err := template.ParseFiles(path) tmpl, err := template.ParseFiles(path)
require.NoError(s.T(), err) require.NoError(s.T(), err)
@@ -504,3 +471,37 @@ func (s *BaseSuite) composeExec(service string, args ...string) string {
return string(content) return string(content)
} }
func (s *BaseSuite) waitForTraefik(containerName string) {
time.Sleep(1 * time.Second)
// Wait for Traefik to turn ready.
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/rawdata", nil)
require.NoError(s.T(), err)
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains(containerName))
require.NoError(s.T(), err)
}
func (s *BaseSuite) displayTraefikLogFile(path string) {
if s.T().Failed() {
if _, err := os.Stat(path); !os.IsNotExist(err) {
content, errRead := os.ReadFile(path)
// TODO TestName
// fmt.Printf("%s: Traefik logs: \n", c.TestName())
fmt.Print("Traefik logs: \n")
if errRead == nil {
fmt.Println(string(content))
} else {
fmt.Println(errRead)
}
} else {
// fmt.Printf("%s: No Traefik logs.\n", c.TestName())
fmt.Print("No Traefik logs.\n")
}
errRemove := os.Remove(path)
if errRemove != nil {
fmt.Println(errRemove)
}
}
}
-1
View File
@@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
package integration package integration
+1
View File
@@ -14,6 +14,7 @@ import (
// Marathon test suites. // Marathon test suites.
type MarathonSuite15 struct { type MarathonSuite15 struct {
BaseSuite BaseSuite
marathonURL string marathonURL string
} }
+1
View File
@@ -16,6 +16,7 @@ const containerNameMarathon = "marathon"
// Marathon test suites. // Marathon test suites.
type MarathonSuite struct { type MarathonSuite struct {
BaseSuite BaseSuite
marathonURL string marathonURL string
} }
+6 -3
View File
@@ -3,6 +3,7 @@ package integration
import ( import (
"bufio" "bufio"
"net" "net"
"strings"
"testing" "testing"
"time" "time"
@@ -15,6 +16,7 @@ import (
type ProxyProtocolSuite struct { type ProxyProtocolSuite struct {
BaseSuite BaseSuite
whoamiIP string whoamiIP string
} }
@@ -124,15 +126,16 @@ func proxyProtoRequest(address string, version byte) (string, error) {
} }
// Read the response from the server // Read the response from the server
var content string var content strings.Builder
scanner := bufio.NewScanner(conn) scanner := bufio.NewScanner(conn)
for scanner.Scan() { for scanner.Scan() {
content += scanner.Text() + "\n" content.WriteString(scanner.Text())
content.WriteString("\n")
} }
if scanner.Err() != nil { if scanner.Err() != nil {
return "", err return "", err
} }
return content, nil return content.String(), nil
} }
+1
View File
@@ -12,6 +12,7 @@ import (
type RateLimitSuite struct { type RateLimitSuite struct {
BaseSuite BaseSuite
ServerIP string ServerIP string
} }
+31 -30
View File
@@ -29,6 +29,7 @@ import (
// Redis test suites. // Redis test suites.
type RedisSentinelSuite struct { type RedisSentinelSuite struct {
BaseSuite BaseSuite
kvClient store.Store kvClient store.Store
redisEndpoints []string redisEndpoints []string
} }
@@ -76,36 +77,6 @@ func (s *RedisSentinelSuite) TearDownSuite() {
} }
} }
func (s *RedisSentinelSuite) setupSentinelConfiguration(ports []string) {
for i, port := range ports {
templateValue := struct{ SentinelPort string }{SentinelPort: port}
// Load file
templateFile := "resources/compose/config/sentinel_template.conf"
tmpl, err := template.ParseFiles(templateFile)
require.NoError(s.T(), err)
folder, prefix := filepath.Split(templateFile)
fileName := fmt.Sprintf("%s/sentinel%d.conf", folder, i+1)
tmpFile, err := os.Create(fileName)
require.NoError(s.T(), err)
defer tmpFile.Close()
err = tmpFile.Chmod(0o666)
require.NoError(s.T(), err)
model := structs.Map(templateValue)
model["SelfFilename"] = tmpFile.Name()
err = tmpl.ExecuteTemplate(tmpFile, prefix, model)
require.NoError(s.T(), err)
err = tmpFile.Sync()
require.NoError(s.T(), err)
}
}
func (s *RedisSentinelSuite) TestSentinelConfiguration() { func (s *RedisSentinelSuite) TestSentinelConfiguration() {
file := s.adaptFile("fixtures/redis/sentinel.toml", struct{ RedisAddress string }{ file := s.adaptFile("fixtures/redis/sentinel.toml", struct{ RedisAddress string }{
RedisAddress: strings.Join(s.redisEndpoints, `","`), RedisAddress: strings.Join(s.redisEndpoints, `","`),
@@ -202,3 +173,33 @@ func (s *RedisSentinelSuite) TestSentinelConfiguration() {
log.WithoutContext().Info(text) log.WithoutContext().Info(text)
} }
} }
func (s *RedisSentinelSuite) setupSentinelConfiguration(ports []string) {
for i, port := range ports {
templateValue := struct{ SentinelPort string }{SentinelPort: port}
// Load file
templateFile := "resources/compose/config/sentinel_template.conf"
tmpl, err := template.ParseFiles(templateFile)
require.NoError(s.T(), err)
folder, prefix := filepath.Split(templateFile)
fileName := fmt.Sprintf("%s/sentinel%d.conf", folder, i+1)
tmpFile, err := os.Create(fileName)
require.NoError(s.T(), err)
defer tmpFile.Close()
err = tmpFile.Chmod(0o666)
require.NoError(s.T(), err)
model := structs.Map(templateValue)
model["SelfFilename"] = tmpFile.Name()
err = tmpl.ExecuteTemplate(tmpFile, prefix, model)
require.NoError(s.T(), err)
err = tmpFile.Sync()
require.NoError(s.T(), err)
}
}
+1
View File
@@ -25,6 +25,7 @@ import (
// Redis test suites. // Redis test suites.
type RedisSuite struct { type RedisSuite struct {
BaseSuite BaseSuite
kvClient store.Store kvClient store.Store
redisEndpoints []string redisEndpoints []string
} }
+1
View File
@@ -18,6 +18,7 @@ import (
type RestSuite struct { type RestSuite struct {
BaseSuite BaseSuite
whoamiAddr string whoamiAddr string
} }
+1
View File
@@ -15,6 +15,7 @@ import (
type RetrySuite struct { type RetrySuite struct {
BaseSuite BaseSuite
whoamiIP string whoamiIP string
} }
+19 -18
View File
@@ -12,6 +12,7 @@ import (
type TracingSuite struct { type TracingSuite struct {
BaseSuite BaseSuite
whoamiIP string whoamiIP string
whoamiPort int whoamiPort int
tracerZipkinIP string tracerZipkinIP string
@@ -43,15 +44,6 @@ func (s *TracingSuite) TearDownSuite() {
s.BaseSuite.TearDownSuite() s.BaseSuite.TearDownSuite()
} }
func (s *TracingSuite) startZipkin() {
s.composeUp("zipkin")
s.tracerZipkinIP = s.getComposeServiceIP("zipkin")
// Wait for Zipkin to turn ready.
err := try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
require.NoError(s.T(), err)
}
func (s *TracingSuite) TestZipkinRateLimit() { func (s *TracingSuite) TestZipkinRateLimit() {
s.startZipkin() s.startZipkin()
@@ -141,15 +133,6 @@ func (s *TracingSuite) TestZipkinAuth() {
require.NoError(s.T(), err) require.NoError(s.T(), err)
} }
func (s *TracingSuite) startJaeger() {
s.composeUp("jaeger", "whoami")
s.tracerJaegerIP = s.getComposeServiceIP("jaeger")
// Wait for Jaeger to turn ready.
err := try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
require.NoError(s.T(), err)
}
func (s *TracingSuite) TestJaegerRateLimit() { func (s *TracingSuite) TestJaegerRateLimit() {
s.startJaeger() s.startJaeger()
// defer s.composeStop(c, "jaeger") // defer s.composeStop(c, "jaeger")
@@ -290,3 +273,21 @@ func (s *TracingSuite) TestJaegerAuthCollector() {
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file")) err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
require.NoError(s.T(), err) require.NoError(s.T(), err)
} }
func (s *TracingSuite) startZipkin() {
s.composeUp("zipkin")
s.tracerZipkinIP = s.getComposeServiceIP("zipkin")
// Wait for Zipkin to turn ready.
err := try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
require.NoError(s.T(), err)
}
func (s *TracingSuite) startJaeger() {
s.composeUp("jaeger", "whoami")
s.tracerJaegerIP = s.getComposeServiceIP("jaeger")
// Wait for Jaeger to turn ready.
err := try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
require.NoError(s.T(), err)
}
+3 -5
View File
@@ -19,6 +19,7 @@ const (
type timedAction func(timeout time.Duration, operation DoCondition) error type timedAction func(timeout time.Duration, operation DoCondition) error
// Sleep pauses the current goroutine for at least the duration d. // Sleep pauses the current goroutine for at least the duration d.
//
// Deprecated: Use only when use another Try[...] functions is not possible. // Deprecated: Use only when use another Try[...] functions is not possible.
func Sleep(d time.Duration) { func Sleep(d time.Duration) {
d = applyCIMultiplier(d) d = applyCIMultiplier(d)
@@ -92,10 +93,7 @@ func Do(timeout time.Duration, operation DoCondition) error {
panic("timeout must be larger than zero") panic("timeout must be larger than zero")
} }
interval := time.Duration(math.Ceil(float64(timeout) / 15.0)) interval := min(time.Duration(math.Ceil(float64(timeout)/15.0)), maxInterval)
if interval > maxInterval {
interval = maxInterval
}
timeout = applyCIMultiplier(timeout) timeout = applyCIMultiplier(timeout)
@@ -166,7 +164,7 @@ func doRequest(action timedAction, timeout time.Duration, request *http.Request,
func applyCIMultiplier(timeout time.Duration) time.Duration { func applyCIMultiplier(timeout time.Duration) time.Duration {
ci := os.Getenv("CI") ci := os.Getenv("CI")
if len(ci) > 0 { if len(ci) > 0 {
log.Debug("Apply CI multiplier:", CITimeoutMultiplier) log.WithoutContext().Debug("Apply CI multiplier:", CITimeoutMultiplier)
return time.Duration(float64(timeout) * CITimeoutMultiplier) return time.Duration(float64(timeout) * CITimeoutMultiplier)
} }
return timeout return timeout
+1
View File
@@ -25,6 +25,7 @@ import (
// Zk test suites. // Zk test suites.
type ZookeeperSuite struct { type ZookeeperSuite struct {
BaseSuite BaseSuite
kvClient store.Store kvClient store.Store
zookeeperAddr string zookeeperAddr string
} }
+13 -13
View File
@@ -78,7 +78,7 @@ func main() {
logger.Fatal(err) logger.Fatal(err)
} }
genStaticConfDoc("./docs/content/reference/static-configuration/env-ref.md", "", func(i interface{}) ([]parser.Flat, error) { genStaticConfDoc("./docs/content/reference/static-configuration/env-ref.md", "", func(i any) ([]parser.Flat, error) {
return env.Encode(env.DefaultNamePrefix, i) return env.Encode(env.DefaultNamePrefix, i)
}) })
genStaticConfDoc("./docs/content/reference/static-configuration/cli-ref.md", "--", flag.Encode) genStaticConfDoc("./docs/content/reference/static-configuration/cli-ref.md", "--", flag.Encode)
@@ -240,7 +240,7 @@ func clean(element any) {
valSvcs.SetMapIndex(reflect.ValueOf(fmt.Sprintf("%s1", valueSvcRoot.Type().Name())), reflect.Value{}) valSvcs.SetMapIndex(reflect.ValueOf(fmt.Sprintf("%s1", valueSvcRoot.Type().Name())), reflect.Value{})
} }
func genStaticConfDoc(outputFile, prefix string, encodeFn func(interface{}) ([]parser.Flat, error)) { func genStaticConfDoc(outputFile, prefix string, encodeFn func(any) ([]parser.Flat, error)) {
logger := log.WithoutContext().WithField("file", outputFile) logger := log.WithoutContext().WithField("file", outputFile)
element := &cmd.NewTraefikConfiguration().Configuration element := &cmd.NewTraefikConfiguration().Configuration
@@ -309,7 +309,7 @@ type errWriter struct {
err error err error
} }
func (ew *errWriter) writeln(a ...interface{}) { func (ew *errWriter) writeln(a ...any) {
if ew.err != nil { if ew.err != nil {
return return
} }
@@ -319,15 +319,15 @@ func (ew *errWriter) writeln(a ...interface{}) {
func genKVDynConfDoc(outputFile string) { func genKVDynConfDoc(outputFile string) {
dynConfPath := "./docs/content/reference/dynamic-configuration/file.toml" dynConfPath := "./docs/content/reference/dynamic-configuration/file.toml"
conf := map[string]interface{}{} conf := map[string]any{}
_, err := toml.DecodeFile(dynConfPath, &conf) _, err := toml.DecodeFile(dynConfPath, &conf)
if err != nil { if err != nil {
log.Fatal(err) log.WithoutContext().Fatal(err)
} }
file, err := os.Create(outputFile) file, err := os.Create(outputFile)
if err != nil { if err != nil {
log.Fatal(err) log.WithoutContext().Fatal(err)
} }
store := storeWriter{data: map[string]string{}} store := storeWriter{data: map[string]string{}}
@@ -335,7 +335,7 @@ func genKVDynConfDoc(outputFile string) {
c := client{store: store} c := client{store: store}
err = c.load("traefik", conf) err = c.load("traefik", conf)
if err != nil { if err != nil {
log.Fatal(err) log.WithoutContext().Fatal(err)
} }
var keys []string var keys []string
@@ -374,10 +374,10 @@ type client struct {
store storeWriter store storeWriter
} }
func (c client) load(parentKey string, conf map[string]interface{}) error { func (c client) load(parentKey string, conf map[string]any) error {
for k, v := range conf { for k, v := range conf {
switch entry := v.(type) { switch entry := v.(type) {
case map[string]interface{}: case map[string]any:
key := path.Join(parentKey, k) key := path.Join(parentKey, k)
if len(entry) == 0 { if len(entry) == 0 {
@@ -391,7 +391,7 @@ func (c client) load(parentKey string, conf map[string]interface{}) error {
return err return err
} }
} }
case []map[string]interface{}: case []map[string]any:
for i, o := range entry { for i, o := range entry {
key := path.Join(parentKey, k, strconv.Itoa(i)) key := path.Join(parentKey, k, strconv.Itoa(i))
@@ -399,11 +399,11 @@ func (c client) load(parentKey string, conf map[string]interface{}) error {
return err return err
} }
} }
case []interface{}: case []any:
for i, o := range entry { for i, o := range entry {
key := path.Join(parentKey, k, strconv.Itoa(i)) key := path.Join(parentKey, k, strconv.Itoa(i))
err := c.store.Put(key, []byte(fmt.Sprintf("%v", o)), nil) err := c.store.Put(key, fmt.Appendf(nil, "%v", o), nil)
if err != nil { if err != nil {
return err return err
} }
@@ -411,7 +411,7 @@ func (c client) load(parentKey string, conf map[string]interface{}) error {
default: default:
key := path.Join(parentKey, k) key := path.Join(parentKey, k)
err := c.store.Put(key, []byte(fmt.Sprintf("%v", v)), nil) err := c.store.Put(key, fmt.Appendf(nil, "%v", v), nil)
if err != nil { if err != nil {
return err return err
} }
+4 -4
View File
@@ -38,7 +38,7 @@ func encodeNode(labels map[string]string, root string, node *parser.Node) {
} }
} }
func encodeRawValue(labels map[string]string, root string, rawValue interface{}) { func encodeRawValue(labels map[string]string, root string, rawValue any) {
if rawValue == nil { if rawValue == nil {
return return
} }
@@ -47,14 +47,14 @@ func encodeRawValue(labels map[string]string, root string, rawValue interface{})
if tValue.Kind() == reflect.Map && tValue.Elem().Kind() == reflect.Interface { if tValue.Kind() == reflect.Map && tValue.Elem().Kind() == reflect.Interface {
r := reflect.ValueOf(rawValue). r := reflect.ValueOf(rawValue).
Convert(reflect.TypeOf((map[string]interface{})(nil))). Convert(reflect.TypeFor[map[string]any]()).
Interface().(map[string]interface{}) Interface().(map[string]any)
for k, v := range r { for k, v := range r {
switch tv := v.(type) { switch tv := v.(type) {
case string: case string:
labels[root+"."+k] = tv labels[root+"."+k] = tv
case []interface{}: case []any:
for i, e := range tv { for i, e := range tv {
encodeRawValue(labels, fmt.Sprintf("%s.%s[%d]", root, k, i), e) encodeRawValue(labels, fmt.Sprintf("%s.%s[%d]", root, k, i), e)
} }
+1 -4
View File
@@ -72,10 +72,7 @@ func pagination(request *http.Request, maximum int) (pageInfo, error) {
return pageInfo{}, fmt.Errorf("invalid request: page: %d, per_page: %d", page, perPage) return pageInfo{}, fmt.Errorf("invalid request: page: %d, per_page: %d", page, perPage)
} }
endIndex := startIndex + perPage endIndex := min(startIndex+perPage, maximum)
if endIndex >= maximum {
endIndex = maximum
}
nextPage := 1 nextPage := 1
if page*perPage < maximum { if page*perPage < maximum {
+1 -1
View File
@@ -15,7 +15,7 @@ func init() {
expvar.Publish("Goroutines2", expvar.Func(goroutines)) expvar.Publish("Goroutines2", expvar.Func(goroutines))
} }
func goroutines() interface{} { func goroutines() any {
return runtime.NumGoroutine() return runtime.NumGoroutine()
} }
+3 -2
View File
@@ -30,6 +30,7 @@ func writeError(rw http.ResponseWriter, msg string, code int) {
type serviceInfoRepresentation struct { type serviceInfoRepresentation struct {
*runtime.ServiceInfo *runtime.ServiceInfo
ServerStatus map[string]string `json:"serverStatus,omitempty"` ServerStatus map[string]string `json:"serverStatus,omitempty"`
} }
@@ -147,12 +148,12 @@ func getProviderName(id string) string {
return strings.SplitN(id, "@", 2)[1] return strings.SplitN(id, "@", 2)[1]
} }
func extractType(element interface{}) string { func extractType(element any) string {
v := reflect.ValueOf(element).Elem() v := reflect.ValueOf(element).Elem()
for i := range v.NumField() { for i := range v.NumField() {
field := v.Field(i) field := v.Field(i)
if field.Kind() == reflect.Map && field.Type().Elem() == reflect.TypeOf(dynamic.PluginConf{}) { if field.Kind() == reflect.Map && field.Type().Elem() == reflect.TypeFor[dynamic.PluginConf]() {
if keys := field.MapKeys(); len(keys) == 1 { if keys := field.MapKeys(); len(keys) == 1 {
return keys[0].String() return keys[0].String()
} }
+1
View File
@@ -15,6 +15,7 @@ import (
type entryPointRepresentation struct { type entryPointRepresentation struct {
*static.EntryPoint *static.EntryPoint
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
} }
+1 -1
View File
@@ -235,7 +235,7 @@ func TestHandler_EntryPoints(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
if *updateExpected { if *updateExpected {
var results interface{} var results any
err := json.Unmarshal(contents, &results) err := json.Unmarshal(contents, &results)
require.NoError(t, err) require.NoError(t, err)
+3
View File
@@ -17,6 +17,7 @@ import (
type routerRepresentation struct { type routerRepresentation struct {
*runtime.RouterInfo *runtime.RouterInfo
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"` Provider string `json:"provider,omitempty"`
} }
@@ -35,6 +36,7 @@ func newRouterRepresentation(name string, rt *runtime.RouterInfo) routerRepresen
type serviceRepresentation struct { type serviceRepresentation struct {
*runtime.ServiceInfo *runtime.ServiceInfo
ServerStatus map[string]string `json:"serverStatus,omitempty"` ServerStatus map[string]string `json:"serverStatus,omitempty"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"` Provider string `json:"provider,omitempty"`
@@ -53,6 +55,7 @@ func newServiceRepresentation(name string, si *runtime.ServiceInfo) serviceRepre
type middlewareRepresentation struct { type middlewareRepresentation struct {
*runtime.MiddlewareInfo *runtime.MiddlewareInfo
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"` Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"` Type string `json:"type,omitempty"`
+1 -1
View File
@@ -950,7 +950,7 @@ func TestHandler_HTTP(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
if *updateExpected { if *updateExpected {
var results interface{} var results any
err := json.Unmarshal(contents, &results) err := json.Unmarshal(contents, &results)
require.NoError(t, err) require.NoError(t, err)
+1 -1
View File
@@ -232,7 +232,7 @@ func getProviders(conf static.Configuration) []string {
if !field.IsNil() { if !field.IsNil() {
providers = append(providers, v.Type().Field(i).Name) providers = append(providers, v.Type().Field(i).Name)
} }
} else if field.Kind() == reflect.Map && field.Type().Elem() == reflect.TypeOf(static.PluginConf{}) { } else if field.Kind() == reflect.Map && field.Type().Elem() == reflect.TypeFor[static.PluginConf]() {
for _, value := range field.MapKeys() { for _, value := range field.MapKeys() {
providers = append(providers, "plugin-"+value.String()) providers = append(providers, "plugin-"+value.String())
} }
+2 -2
View File
@@ -243,7 +243,7 @@ func TestHandler_Overview(t *testing.T) {
Rest: &rest.Provider{}, Rest: &rest.Provider{},
Rancher: &rancher.Provider{}, Rancher: &rancher.Provider{},
Plugin: map[string]static.PluginConf{ Plugin: map[string]static.PluginConf{
"test": map[string]interface{}{}, "test": map[string]any{},
}, },
}, },
}, },
@@ -298,7 +298,7 @@ func TestHandler_Overview(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
if *updateExpected { if *updateExpected {
var results interface{} var results any
err := json.Unmarshal(contents, &results) err := json.Unmarshal(contents, &results)
require.NoError(t, err) require.NoError(t, err)
+3
View File
@@ -16,6 +16,7 @@ import (
type tcpRouterRepresentation struct { type tcpRouterRepresentation struct {
*runtime.TCPRouterInfo *runtime.TCPRouterInfo
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"` Provider string `json:"provider,omitempty"`
} }
@@ -30,6 +31,7 @@ func newTCPRouterRepresentation(name string, rt *runtime.TCPRouterInfo) tcpRoute
type tcpServiceRepresentation struct { type tcpServiceRepresentation struct {
*runtime.TCPServiceInfo *runtime.TCPServiceInfo
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"` Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"` Type string `json:"type,omitempty"`
@@ -46,6 +48,7 @@ func newTCPServiceRepresentation(name string, si *runtime.TCPServiceInfo) tcpSer
type tcpMiddlewareRepresentation struct { type tcpMiddlewareRepresentation struct {
*runtime.TCPMiddlewareInfo *runtime.TCPMiddlewareInfo
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"` Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"` Type string `json:"type,omitempty"`
+1 -1
View File
@@ -821,7 +821,7 @@ func TestHandler_TCP(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
if *updateExpected { if *updateExpected {
var results interface{} var results any
err := json.Unmarshal(contents, &results) err := json.Unmarshal(contents, &results)
require.NoError(t, err) require.NoError(t, err)
+1 -1
View File
@@ -178,7 +178,7 @@ func TestHandler_GetMiddleware(t *testing.T) {
middlewareName string middlewareName string
conf runtime.Configuration conf runtime.Configuration
expectedStatus int expectedStatus int
expected interface{} expected any
}{ }{
{ {
desc: "Middleware not found", desc: "Middleware not found",
+2
View File
@@ -16,6 +16,7 @@ import (
type udpRouterRepresentation struct { type udpRouterRepresentation struct {
*runtime.UDPRouterInfo *runtime.UDPRouterInfo
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"` Provider string `json:"provider,omitempty"`
} }
@@ -30,6 +31,7 @@ func newUDPRouterRepresentation(name string, rt *runtime.UDPRouterInfo) udpRoute
type udpServiceRepresentation struct { type udpServiceRepresentation struct {
*runtime.UDPServiceInfo *runtime.UDPServiceInfo
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"` Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"` Type string `json:"type,omitempty"`
+1 -1
View File
@@ -560,7 +560,7 @@ func TestHandler_UDP(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
if *updateExpected { if *updateExpected {
var results interface{} var results any
err := json.Unmarshal(contents, &results) err := json.Unmarshal(contents, &results)
require.NoError(t, err) require.NoError(t, err)
+1 -1
View File
@@ -63,7 +63,7 @@ func (f *FileLoader) Load(args []string, cmd *cli.Command) (bool, error) {
// loadConfigFiles tries to decode the given configuration file and all default locations for the configuration file. // loadConfigFiles tries to decode the given configuration file and all default locations for the configuration file.
// It stops as soon as decoding one of them is successful. // It stops as soon as decoding one of them is successful.
func loadConfigFiles(configFile string, element interface{}) (string, error) { func loadConfigFiles(configFile string, element any) (string, error) {
finder := cli.Finder{ finder := cli.Finder{
BasePaths: []string{"/etc/traefik/traefik", "$XDG_CONFIG_HOME/traefik", "$HOME/.config/traefik", "./traefik"}, BasePaths: []string{"/etc/traefik/traefik", "$XDG_CONFIG_HOME/traefik", "$HOME/.config/traefik", "./traefik"},
Extensions: []string{"toml", "yaml", "yml"}, Extensions: []string{"toml", "yaml", "yml"},
+3 -3
View File
@@ -18,7 +18,7 @@ const (
) )
// Hydrate hydrates a configuration. // Hydrate hydrates a configuration.
func Hydrate(element interface{}) error { func Hydrate(element any) error {
field := reflect.ValueOf(element) field := reflect.ValueOf(element)
return fill(field) return fill(field)
} }
@@ -55,7 +55,7 @@ func fill(field reflect.Value) error {
setTyped(field, int32(defaultNumber)) setTyped(field, int32(defaultNumber))
case reflect.Int64: case reflect.Int64:
switch field.Type() { switch field.Type() {
case reflect.TypeOf(types.Duration(time.Second)): case reflect.TypeFor[types.Duration]():
setTyped(field, types.Duration(defaultNumber*time.Second)) setTyped(field, types.Duration(defaultNumber*time.Second))
default: default:
setTyped(field, int64(defaultNumber)) setTyped(field, int64(defaultNumber))
@@ -81,7 +81,7 @@ func fill(field reflect.Value) error {
return nil return nil
} }
func setTyped(field reflect.Value, i interface{}) { func setTyped(field reflect.Value, i any) {
baseValue := reflect.ValueOf(i) baseValue := reflect.ValueOf(i)
if field.Kind().String() == field.Type().String() { if field.Kind().String() == field.Type().String() {
field.Set(baseValue) field.Set(baseValue)
+2 -2
View File
@@ -21,7 +21,7 @@ func TestDeepCopy(t *testing.T) {
cfgDeepCopy := cfg.DeepCopy() cfgDeepCopy := cfg.DeepCopy()
assert.NotEqual(t, reflect.ValueOf(cfgDeepCopy), reflect.ValueOf(cfg)) assert.NotEqual(t, reflect.ValueOf(cfgDeepCopy), reflect.ValueOf(cfg))
assert.Equal(t, reflect.TypeOf(cfgDeepCopy), reflect.TypeOf(cfg)) assert.Equal(t, reflect.TypeOf(cfgDeepCopy), reflect.TypeOf(cfg)) //nolint:modernize // Comparing runtime types of two values.
assert.Equal(t, cfgDeepCopy, cfg) assert.Equal(t, cfgDeepCopy, cfg)
// Update cfg // Update cfg
@@ -32,6 +32,6 @@ func TestDeepCopy(t *testing.T) {
assert.Equal(t, cfgCopy, cfg) assert.Equal(t, cfgCopy, cfg)
assert.NotEqual(t, reflect.ValueOf(cfgDeepCopy), reflect.ValueOf(cfg)) assert.NotEqual(t, reflect.ValueOf(cfgDeepCopy), reflect.ValueOf(cfg))
assert.Equal(t, reflect.TypeOf(cfgDeepCopy), reflect.TypeOf(cfg)) assert.Equal(t, reflect.TypeOf(cfgDeepCopy), reflect.TypeOf(cfg)) //nolint:modernize // Comparing runtime types of two values.
assert.NotEqual(t, cfgDeepCopy, cfg) assert.NotEqual(t, cfgDeepCopy, cfg)
} }
+1
View File
@@ -389,6 +389,7 @@ func (s *IPStrategy) Get() (ip.Strategy, error) {
// IPWhiteList holds the IP whitelist middleware configuration. // IPWhiteList holds the IP whitelist middleware configuration.
// This middleware limits allowed requests based on the client IP. // This middleware limits allowed requests based on the client IP.
// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
//
// Deprecated: please use IPAllowList instead. // Deprecated: please use IPAllowList instead.
type IPWhiteList struct { type IPWhiteList struct {
// SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). Required. // SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). Required.
+3 -3
View File
@@ -44,11 +44,11 @@ func TestPluginConf_DeepCopy_mapOfStruct(t *testing.T) {
} }
func TestPluginConf_DeepCopy_map(t *testing.T) { func TestPluginConf_DeepCopy_map(t *testing.T) {
m := map[string]interface{}{ m := map[string]any{
"name": "bar", "name": "bar",
} }
p := PluginConf{ p := PluginConf{
"config": map[string]interface{}{ "config": map[string]any{
"foo": m, "foo": m,
}, },
} }
@@ -64,7 +64,7 @@ func TestPluginConf_DeepCopy_map(t *testing.T) {
func TestPluginConf_DeepCopy_panic(t *testing.T) { func TestPluginConf_DeepCopy_panic(t *testing.T) {
p := &PluginConf{ p := &PluginConf{
"config": map[string]interface{}{ "config": map[string]any{
"foo": &Foo{Name: "gigi"}, "foo": &Foo{Name: "gigi"},
}, },
} }
+1
View File
@@ -26,6 +26,7 @@ type TCPInFlightConn struct {
// TCPIPWhiteList holds the TCP IPWhiteList middleware configuration. // TCPIPWhiteList holds the TCP IPWhiteList middleware configuration.
// This middleware limits allowed requests based on the client IP. // This middleware limits allowed requests based on the client IP.
// More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/ // More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
//
// Deprecated: please use IPAllowList instead. // Deprecated: please use IPAllowList instead.
type TCPIPWhiteList struct { type TCPIPWhiteList struct {
// SourceRange defines the allowed IPs (or ranges of allowed IPs by using CIDR notation). // SourceRange defines the allowed IPs (or ranges of allowed IPs by using CIDR notation).
+2 -2
View File
@@ -13,7 +13,7 @@ import (
// KV pairs -> tree of untyped nodes // KV pairs -> tree of untyped nodes
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element) // untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
// "typed" nodes -> typed element. // "typed" nodes -> typed element.
func Decode(pairs []*store.KVPair, element interface{}, rootName string) error { func Decode(pairs []*store.KVPair, element any, rootName string) error {
if element == nil { if element == nil {
return nil return nil
} }
@@ -34,7 +34,7 @@ func Decode(pairs []*store.KVPair, element interface{}, rootName string) error {
return parser.Fill(element, node, parser.FillerOpts{AllowSliceAsStruct: false}) return parser.Fill(element, node, parser.FillerOpts{AllowSliceAsStruct: false})
} }
func getRootFieldNames(rootName string, element interface{}) []string { func getRootFieldNames(rootName string, element any) []string {
if element == nil { if element == nil {
return nil return nil
} }
+1 -1
View File
@@ -31,6 +31,6 @@ func EncodeConfiguration(conf *dynamic.Configuration) (map[string]string, error)
// Decode converts the labels to an element. // Decode converts the labels to an element.
// labels -> [ node -> node + metadata (type) ] -> element (node). // labels -> [ node -> node + metadata (type) ] -> element (node).
func Decode(labels map[string]string, element interface{}, filters ...string) error { func Decode(labels map[string]string, element any, filters ...string) error {
return parser.Decode(labels, element, parser.DefaultRootName, filters...) return parser.Decode(labels, element, parser.DefaultRootName, filters...)
} }
+11 -17
View File
@@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"maps"
"slices" "slices"
"sort" "sort"
"sync" "sync"
@@ -72,6 +73,7 @@ func unique(src []string) []string {
// RouterInfo holds information about a currently running HTTP router. // RouterInfo holds information about a currently running HTTP router.
type RouterInfo struct { type RouterInfo struct {
*dynamic.Router // dynamic configuration *dynamic.Router // dynamic configuration
// Err contains all the errors that occurred during router's creation. // Err contains all the errors that occurred during router's creation.
Err []string `json:"error,omitempty"` Err []string `json:"error,omitempty"`
// Status reports whether the router is disabled, in a warning state, or all good (enabled). // Status reports whether the router is disabled, in a warning state, or all good (enabled).
@@ -84,10 +86,8 @@ type RouterInfo struct {
// AddError adds err to r.Err, if it does not already exist. // AddError adds err to r.Err, if it does not already exist.
// If critical is set, r is marked as disabled. // If critical is set, r is marked as disabled.
func (r *RouterInfo) AddError(err error, critical bool) { func (r *RouterInfo) AddError(err error, critical bool) {
for _, value := range r.Err { if slices.Contains(r.Err, err.Error()) {
if value == err.Error() { return
return
}
} }
r.Err = append(r.Err, err.Error()) r.Err = append(r.Err, err.Error())
@@ -105,6 +105,7 @@ func (r *RouterInfo) AddError(err error, critical bool) {
// MiddlewareInfo holds information about a currently running middleware. // MiddlewareInfo holds information about a currently running middleware.
type MiddlewareInfo struct { type MiddlewareInfo struct {
*dynamic.Middleware // dynamic configuration *dynamic.Middleware // dynamic configuration
// Err contains all the errors that occurred during service creation. // Err contains all the errors that occurred during service creation.
Err []string `json:"error,omitempty"` Err []string `json:"error,omitempty"`
Status string `json:"status,omitempty"` Status string `json:"status,omitempty"`
@@ -114,10 +115,8 @@ type MiddlewareInfo struct {
// AddError adds err to s.Err, if it does not already exist. // AddError adds err to s.Err, if it does not already exist.
// If critical is set, m is marked as disabled. // If critical is set, m is marked as disabled.
func (m *MiddlewareInfo) AddError(err error, critical bool) { func (m *MiddlewareInfo) AddError(err error, critical bool) {
for _, value := range m.Err { if slices.Contains(m.Err, err.Error()) {
if value == err.Error() { return
return
}
} }
m.Err = append(m.Err, err.Error()) m.Err = append(m.Err, err.Error())
@@ -135,6 +134,7 @@ func (m *MiddlewareInfo) AddError(err error, critical bool) {
// ServiceInfo holds information about a currently running service. // ServiceInfo holds information about a currently running service.
type ServiceInfo struct { type ServiceInfo struct {
*dynamic.Service // dynamic configuration *dynamic.Service // dynamic configuration
// Err contains all the errors that occurred during service creation. // Err contains all the errors that occurred during service creation.
Err []string `json:"error,omitempty"` Err []string `json:"error,omitempty"`
// Status reports whether the service is disabled, in a warning state, or all good (enabled). // Status reports whether the service is disabled, in a warning state, or all good (enabled).
@@ -150,10 +150,8 @@ type ServiceInfo struct {
// AddError adds err to s.Err, if it does not already exist. // AddError adds err to s.Err, if it does not already exist.
// If critical is set, s is marked as disabled. // If critical is set, s is marked as disabled.
func (s *ServiceInfo) AddError(err error, critical bool) { func (s *ServiceInfo) AddError(err error, critical bool) {
for _, value := range s.Err { if slices.Contains(s.Err, err.Error()) {
if value == err.Error() { return
return
}
} }
s.Err = append(s.Err, err.Error()) s.Err = append(s.Err, err.Error())
@@ -190,9 +188,5 @@ func (s *ServiceInfo) GetAllStatus() map[string]string {
return nil return nil
} }
allStatus := make(map[string]string, len(s.serverStatus)) return maps.Clone(s.serverStatus)
for k, v := range s.serverStatus {
allStatus[k] = v
}
return allStatus
} }
+13 -16
View File
@@ -47,8 +47,9 @@ func (c *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoi
// TCPRouterInfo holds information about a currently running TCP router. // TCPRouterInfo holds information about a currently running TCP router.
type TCPRouterInfo struct { type TCPRouterInfo struct {
*dynamic.TCPRouter // dynamic configuration *dynamic.TCPRouter // dynamic configuration
Err []string `json:"error,omitempty"` // initialization error
Err []string `json:"error,omitempty"` // initialization error
// Status reports whether the router is disabled, in a warning state, or all good (enabled). // Status reports whether the router is disabled, in a warning state, or all good (enabled).
// If not in "enabled" state, the reason for it should be in the list of Err. // If not in "enabled" state, the reason for it should be in the list of Err.
// It is the caller's responsibility to set the initial status. // It is the caller's responsibility to set the initial status.
@@ -59,10 +60,8 @@ type TCPRouterInfo struct {
// AddError adds err to r.Err, if it does not already exist. // AddError adds err to r.Err, if it does not already exist.
// If critical is set, r is marked as disabled. // If critical is set, r is marked as disabled.
func (r *TCPRouterInfo) AddError(err error, critical bool) { func (r *TCPRouterInfo) AddError(err error, critical bool) {
for _, value := range r.Err { if slices.Contains(r.Err, err.Error()) {
if value == err.Error() { return
return
}
} }
r.Err = append(r.Err, err.Error()) r.Err = append(r.Err, err.Error())
@@ -79,8 +78,9 @@ func (r *TCPRouterInfo) AddError(err error, critical bool) {
// TCPServiceInfo holds information about a currently running TCP service. // TCPServiceInfo holds information about a currently running TCP service.
type TCPServiceInfo struct { type TCPServiceInfo struct {
*dynamic.TCPService // dynamic configuration *dynamic.TCPService // dynamic configuration
Err []string `json:"error,omitempty"` // initialization error
Err []string `json:"error,omitempty"` // initialization error
// Status reports whether the service is disabled, in a warning state, or all good (enabled). // Status reports whether the service is disabled, in a warning state, or all good (enabled).
// If not in "enabled" state, the reason for it should be in the list of Err. // If not in "enabled" state, the reason for it should be in the list of Err.
// It is the caller's responsibility to set the initial status. // It is the caller's responsibility to set the initial status.
@@ -91,10 +91,8 @@ type TCPServiceInfo struct {
// AddError adds err to s.Err, if it does not already exist. // AddError adds err to s.Err, if it does not already exist.
// If critical is set, s is marked as disabled. // If critical is set, s is marked as disabled.
func (s *TCPServiceInfo) AddError(err error, critical bool) { func (s *TCPServiceInfo) AddError(err error, critical bool) {
for _, value := range s.Err { if slices.Contains(s.Err, err.Error()) {
if value == err.Error() { return
return
}
} }
s.Err = append(s.Err, err.Error()) s.Err = append(s.Err, err.Error())
@@ -112,6 +110,7 @@ func (s *TCPServiceInfo) AddError(err error, critical bool) {
// TCPMiddlewareInfo holds information about a currently running middleware. // TCPMiddlewareInfo holds information about a currently running middleware.
type TCPMiddlewareInfo struct { type TCPMiddlewareInfo struct {
*dynamic.TCPMiddleware // dynamic configuration *dynamic.TCPMiddleware // dynamic configuration
// Err contains all the errors that occurred during service creation. // Err contains all the errors that occurred during service creation.
Err []string `json:"error,omitempty"` Err []string `json:"error,omitempty"`
Status string `json:"status,omitempty"` Status string `json:"status,omitempty"`
@@ -121,10 +120,8 @@ type TCPMiddlewareInfo struct {
// AddError adds err to s.Err, if it does not already exist. // AddError adds err to s.Err, if it does not already exist.
// If critical is set, m is marked as disabled. // If critical is set, m is marked as disabled.
func (m *TCPMiddlewareInfo) AddError(err error, critical bool) { func (m *TCPMiddlewareInfo) AddError(err error, critical bool) {
for _, value := range m.Err { if slices.Contains(m.Err, err.Error()) {
if value == err.Error() { return
return
}
} }
m.Err = append(m.Err, err.Error()) m.Err = append(m.Err, err.Error())
+10 -12
View File
@@ -53,8 +53,9 @@ func (c *Configuration) GetUDPRoutersByEntryPoints(ctx context.Context, entryPoi
// UDPRouterInfo holds information about a currently running UDP router. // UDPRouterInfo holds information about a currently running UDP router.
type UDPRouterInfo struct { type UDPRouterInfo struct {
*dynamic.UDPRouter // dynamic configuration *dynamic.UDPRouter // dynamic configuration
Err []string `json:"error,omitempty"` // initialization error
Err []string `json:"error,omitempty"` // initialization error
// Status reports whether the router is disabled, in a warning state, or all good (enabled). // Status reports whether the router is disabled, in a warning state, or all good (enabled).
// If not in "enabled" state, the reason for it should be in the list of Err. // If not in "enabled" state, the reason for it should be in the list of Err.
// It is the caller's responsibility to set the initial status. // It is the caller's responsibility to set the initial status.
@@ -65,10 +66,8 @@ type UDPRouterInfo struct {
// AddError adds err to r.Err, if it does not already exist. // AddError adds err to r.Err, if it does not already exist.
// If critical is set, r is marked as disabled. // If critical is set, r is marked as disabled.
func (r *UDPRouterInfo) AddError(err error, critical bool) { func (r *UDPRouterInfo) AddError(err error, critical bool) {
for _, value := range r.Err { if slices.Contains(r.Err, err.Error()) {
if value == err.Error() { return
return
}
} }
r.Err = append(r.Err, err.Error()) r.Err = append(r.Err, err.Error())
@@ -85,8 +84,9 @@ func (r *UDPRouterInfo) AddError(err error, critical bool) {
// UDPServiceInfo holds information about a currently running UDP service. // UDPServiceInfo holds information about a currently running UDP service.
type UDPServiceInfo struct { type UDPServiceInfo struct {
*dynamic.UDPService // dynamic configuration *dynamic.UDPService // dynamic configuration
Err []string `json:"error,omitempty"` // initialization error
Err []string `json:"error,omitempty"` // initialization error
// Status reports whether the service is disabled, in a warning state, or all good (enabled). // Status reports whether the service is disabled, in a warning state, or all good (enabled).
// If not in "enabled" state, the reason for it should be in the list of Err. // If not in "enabled" state, the reason for it should be in the list of Err.
// It is the caller's responsibility to set the initial status. // It is the caller's responsibility to set the initial status.
@@ -97,10 +97,8 @@ type UDPServiceInfo struct {
// AddError adds err to s.Err, if it does not already exist. // AddError adds err to s.Err, if it does not already exist.
// If critical is set, s is marked as disabled. // If critical is set, s is marked as disabled.
func (s *UDPServiceInfo) AddError(err error, critical bool) { func (s *UDPServiceInfo) AddError(err error, critical bool) {
for _, value := range s.Err { if slices.Contains(s.Err, err.Error()) {
if value == err.Error() { return
return
}
} }
s.Err = append(s.Err, err.Error()) s.Err = append(s.Err, err.Error())
+1 -1
View File
@@ -1,4 +1,4 @@
package static package static
// PluginConf holds the plugin configuration. // PluginConf holds the plugin configuration.
type PluginConf map[string]interface{} type PluginConf map[string]any
+14 -14
View File
@@ -295,20 +295,6 @@ func (c *Configuration) SetEffectiveConfiguration() {
c.initACMEProvider() c.initACMEProvider()
} }
func (c *Configuration) hasUserDefinedEntrypoint() bool {
return len(c.EntryPoints) != 0
}
func (c *Configuration) initACMEProvider() {
for _, resolver := range c.CertificatesResolvers {
if resolver.ACME != nil {
resolver.ACME.CAServer = getSafeACMECAServer(resolver.ACME.CAServer)
}
}
legolog.Logger = stdlog.New(log.WithoutContext().WriterLevel(logrus.DebugLevel), "legolog: ", 0)
}
// ValidateConfiguration validate that configuration is coherent. // ValidateConfiguration validate that configuration is coherent.
func (c *Configuration) ValidateConfiguration() error { func (c *Configuration) ValidateConfiguration() error {
var acmeEmail string var acmeEmail string
@@ -342,6 +328,20 @@ func (c *Configuration) ValidateConfiguration() error {
return nil return nil
} }
func (c *Configuration) hasUserDefinedEntrypoint() bool {
return len(c.EntryPoints) != 0
}
func (c *Configuration) initACMEProvider() {
for _, resolver := range c.CertificatesResolvers {
if resolver.ACME != nil {
resolver.ACME.CAServer = getSafeACMECAServer(resolver.ACME.CAServer)
}
}
legolog.Logger = stdlog.New(log.WithoutContext().WriterLevel(logrus.DebugLevel), "legolog: ", 0)
}
func getSafeACMECAServer(caServerSrc string) string { func getSafeACMECAServer(caServerSrc string) string {
if len(caServerSrc) == 0 { if len(caServerSrc) == 0 {
return DefaultAcmeCAServer return DefaultAcmeCAServer
+19 -17
View File
@@ -82,10 +82,19 @@ type backendURL struct {
// BackendConfig HealthCheck configuration for a backend. // BackendConfig HealthCheck configuration for a backend.
type BackendConfig struct { type BackendConfig struct {
Options Options
name string name string
disabledURLs []backendURL disabledURLs []backendURL
} }
// NewBackendConfig Instantiate a new BackendConfig.
func NewBackendConfig(options Options, backendName string) *BackendConfig {
return &BackendConfig{
Options: options,
name: backendName,
}
}
func (b *BackendConfig) newRequest(serverURL *url.URL) (*http.Request, error) { func (b *BackendConfig) newRequest(serverURL *url.URL) (*http.Request, error) {
u, err := serverURL.Parse(b.Path) u, err := serverURL.Parse(b.Path)
if err != nil { if err != nil {
@@ -236,14 +245,6 @@ func newHealthCheck(registry metrics.Registry) *HealthCheck {
} }
} }
// NewBackendConfig Instantiate a new BackendConfig.
func NewBackendConfig(options Options, backendName string) *BackendConfig {
return &BackendConfig{
Options: options,
name: backendName,
}
}
// checkHealth returns a nil error in case it was successful and otherwise // checkHealth returns a nil error in case it was successful and otherwise
// a non-nil error with a meaningful description why the health check failed. // a non-nil error with a meaningful description why the health check failed.
func checkHealth(serverURL *url.URL, backend *BackendConfig) error { func checkHealth(serverURL *url.URL, backend *BackendConfig) error {
@@ -286,6 +287,16 @@ type StatusUpdater interface {
RegisterStatusUpdater(fn func(up bool)) error RegisterStatusUpdater(fn func(up bool)) error
} }
// LbStatusUpdater wraps a BalancerHandler and a ServiceInfo,
// so it can keep track of the status of a server in the ServiceInfo.
type LbStatusUpdater struct {
BalancerHandler
serviceInfo *runtime.ServiceInfo // can be nil
updaters []func(up bool)
wantsHealthCheck bool
}
// NewLBStatusUpdater returns a new LbStatusUpdater. // NewLBStatusUpdater returns a new LbStatusUpdater.
func NewLBStatusUpdater(bh BalancerHandler, info *runtime.ServiceInfo, hc *dynamic.ServerHealthCheck) *LbStatusUpdater { func NewLBStatusUpdater(bh BalancerHandler, info *runtime.ServiceInfo, hc *dynamic.ServerHealthCheck) *LbStatusUpdater {
return &LbStatusUpdater{ return &LbStatusUpdater{
@@ -295,15 +306,6 @@ func NewLBStatusUpdater(bh BalancerHandler, info *runtime.ServiceInfo, hc *dynam
} }
} }
// LbStatusUpdater wraps a BalancerHandler and a ServiceInfo,
// so it can keep track of the status of a server in the ServiceInfo.
type LbStatusUpdater struct {
BalancerHandler
serviceInfo *runtime.ServiceInfo // can be nil
updaters []func(up bool)
wantsHealthCheck bool
}
// RegisterStatusUpdater adds fn to the list of hooks that are run when the // RegisterStatusUpdater adds fn to the list of hooks that are run when the
// status of the Balancer changes. // status of the Balancer changes.
// Not thread safe. // Not thread safe.
+1
View File
@@ -456,6 +456,7 @@ type testLoadBalancer struct {
// RWMutex needed due to parallel test execution: Both the system-under-test // RWMutex needed due to parallel test execution: Both the system-under-test
// and the test assertions reference the counters. // and the test assertions reference the counters.
*sync.RWMutex *sync.RWMutex
numRemovedServers int numRemovedServers int
numUpsertedServers int numUpsertedServers int
servers []*url.URL servers []*url.URL
+1
View File
@@ -17,6 +17,7 @@ const (
// If operation() takes more than MinJobInterval, Reset() is called in NextBackOff(). // If operation() takes more than MinJobInterval, Reset() is called in NextBackOff().
type BackOff struct { type BackOff struct {
*backoff.ExponentialBackOff *backoff.ExponentialBackOff
MinJobInterval time.Duration MinJobInterval time.Duration
} }
+24 -13
View File
@@ -9,68 +9,79 @@ import (
) )
// Debug logs a message at level Debug on the standard logger. // Debug logs a message at level Debug on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Debug(...) instead. // Deprecated: use log.FromContext(ctx).Debug(...) instead.
func Debug(args ...interface{}) { func Debug(args ...any) {
mainLogger.Debug(args...) mainLogger.Debug(args...)
} }
// Debugf logs a message at level Debug on the standard logger. // Debugf logs a message at level Debug on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Debugf(...) instead. // Deprecated: use log.FromContext(ctx).Debugf(...) instead.
func Debugf(format string, args ...interface{}) { func Debugf(format string, args ...any) {
mainLogger.Debugf(format, args...) mainLogger.Debugf(format, args...)
} }
// Info logs a message at level Info on the standard logger. // Info logs a message at level Info on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Info(...) instead. // Deprecated: use log.FromContext(ctx).Info(...) instead.
func Info(args ...interface{}) { func Info(args ...any) {
mainLogger.Info(args...) mainLogger.Info(args...)
} }
// Infof logs a message at level Info on the standard logger. // Infof logs a message at level Info on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Infof(...) instead. // Deprecated: use log.FromContext(ctx).Infof(...) instead.
func Infof(format string, args ...interface{}) { func Infof(format string, args ...any) {
mainLogger.Infof(format, args...) mainLogger.Infof(format, args...)
} }
// Warn logs a message at level Warn on the standard logger. // Warn logs a message at level Warn on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Warn(...) instead. // Deprecated: use log.FromContext(ctx).Warn(...) instead.
func Warn(args ...interface{}) { func Warn(args ...any) {
mainLogger.Warn(args...) mainLogger.Warn(args...)
} }
// Warnf logs a message at level Warn on the standard logger. // Warnf logs a message at level Warn on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Warnf(...) instead. // Deprecated: use log.FromContext(ctx).Warnf(...) instead.
func Warnf(format string, args ...interface{}) { func Warnf(format string, args ...any) {
mainLogger.Warnf(format, args...) mainLogger.Warnf(format, args...)
} }
// Error logs a message at level Error on the standard logger. // Error logs a message at level Error on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Error(...) instead. // Deprecated: use log.FromContext(ctx).Error(...) instead.
func Error(args ...interface{}) { func Error(args ...any) {
mainLogger.Error(args...) mainLogger.Error(args...)
} }
// Errorf logs a message at level Error on the standard logger. // Errorf logs a message at level Error on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Errorf(...) instead. // Deprecated: use log.FromContext(ctx).Errorf(...) instead.
func Errorf(format string, args ...interface{}) { func Errorf(format string, args ...any) {
mainLogger.Errorf(format, args...) mainLogger.Errorf(format, args...)
} }
// Panic logs a message at level Panic on the standard logger. // Panic logs a message at level Panic on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Panic(...) instead. // Deprecated: use log.FromContext(ctx).Panic(...) instead.
func Panic(args ...interface{}) { func Panic(args ...any) {
mainLogger.Panic(args...) mainLogger.Panic(args...)
} }
// Fatal logs a message at level Fatal on the standard logger. // Fatal logs a message at level Fatal on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Fatal(...) instead. // Deprecated: use log.FromContext(ctx).Fatal(...) instead.
func Fatal(args ...interface{}) { func Fatal(args ...any) {
mainLogger.Fatal(args...) mainLogger.Fatal(args...)
} }
// Fatalf logs a message at level Fatal on the standard logger. // Fatalf logs a message at level Fatal on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Fatalf(...) instead. // Deprecated: use log.FromContext(ctx).Fatalf(...) instead.
func Fatalf(format string, args ...interface{}) { func Fatalf(format string, args ...any) {
mainLogger.Fatalf(format, args...) mainLogger.Fatalf(format, args...)
} }
@@ -84,7 +95,7 @@ func AddHook(hook logrus.Hook) {
func CustomWriterLevel(level logrus.Level, maxScanTokenSize int) *io.PipeWriter { func CustomWriterLevel(level logrus.Level, maxScanTokenSize int) *io.PipeWriter {
reader, writer := io.Pipe() reader, writer := io.Pipe()
var printFunc func(args ...interface{}) var printFunc func(args ...any)
switch level { switch level {
case logrus.DebugLevel: case logrus.DebugLevel:
@@ -111,7 +122,7 @@ func CustomWriterLevel(level logrus.Level, maxScanTokenSize int) *io.PipeWriter
// extract from github.com/Sirupsen/logrus/writer.go // extract from github.com/Sirupsen/logrus/writer.go
// Hack the buffer size. // Hack the buffer size.
func writerScanner(reader io.ReadCloser, scanTokenSize int, printFunc func(args ...interface{})) { func writerScanner(reader io.ReadCloser, scanTokenSize int, printFunc func(args ...any)) {
scanner := bufio.NewScanner(reader) scanner := bufio.NewScanner(reader)
if scanTokenSize > bufio.MaxScanTokenSize { if scanTokenSize > bufio.MaxScanTokenSize {
+1 -1
View File
@@ -58,7 +58,7 @@ func RegisterDatadog(ctx context.Context, config *types.Datadog) Registry {
config.Prefix = defaultMetricsPrefix config.Prefix = defaultMetricsPrefix
} }
datadogClient = dogstatsd.New(config.Prefix+".", kitlog.LoggerFunc(func(keyvals ...interface{}) error { datadogClient = dogstatsd.New(config.Prefix+".", kitlog.LoggerFunc(func(keyvals ...any) error {
log.WithoutContext().WithField(log.MetricsProviderName, "datadog").Info(keyvals...) log.WithoutContext().WithField(log.MetricsProviderName, "datadog").Info(keyvals...)
return nil return nil
})) }))
+5 -5
View File
@@ -36,16 +36,16 @@ func (c MultiCounterWithHeaders) With(headers http.Header, labelValues ...string
return next return next
} }
// NewCounterWithNoopHeaders returns a CounterWithNoopHeaders.
func NewCounterWithNoopHeaders(counter metrics.Counter) CounterWithNoopHeaders {
return CounterWithNoopHeaders{counter: counter}
}
// CounterWithNoopHeaders is a counter that satisfies CounterWithHeaders but ignores the given http.Header. // CounterWithNoopHeaders is a counter that satisfies CounterWithHeaders but ignores the given http.Header.
type CounterWithNoopHeaders struct { type CounterWithNoopHeaders struct {
counter metrics.Counter counter metrics.Counter
} }
// NewCounterWithNoopHeaders returns a CounterWithNoopHeaders.
func NewCounterWithNoopHeaders(counter metrics.Counter) CounterWithNoopHeaders {
return CounterWithNoopHeaders{counter: counter}
}
// Add adds the given delta value to the counter value. // Add adds the given delta value to the counter value.
func (c CounterWithNoopHeaders) Add(delta float64) { func (c CounterWithNoopHeaders) Add(delta float64) {
c.counter.Add(delta) c.counter.Add(delta)
+1 -1
View File
@@ -147,7 +147,7 @@ func initInfluxDBClient(ctx context.Context, config *types.InfluxDB) *influx.Inf
Database: config.Database, Database: config.Database,
RetentionPolicy: config.RetentionPolicy, RetentionPolicy: config.RetentionPolicy,
}, },
kitlog.LoggerFunc(func(keyvals ...interface{}) error { kitlog.LoggerFunc(func(keyvals ...any) error {
log.WithoutContext().WithField(log.MetricsProviderName, "influxdb").Info(keyvals...) log.WithoutContext().WithField(log.MetricsProviderName, "influxdb").Info(keyvals...)
return nil return nil
})) }))
+1 -1
View File
@@ -37,7 +37,7 @@ func RegisterInfluxDB2(ctx context.Context, config *types.InfluxDB2) Registry {
influxDB2Store = influx.New( influxDB2Store = influx.New(
config.AdditionalLabels, config.AdditionalLabels,
influxdb.BatchPointsConfig{}, influxdb.BatchPointsConfig{},
kitlog.LoggerFunc(func(kv ...interface{}) error { kitlog.LoggerFunc(func(kv ...any) error {
log.FromContext(ctx).Error(kv...) log.FromContext(ctx).Error(kv...)
return nil return nil
}), }),
+1 -1
View File
@@ -55,7 +55,7 @@ func RegisterStatsd(ctx context.Context, config *types.Statsd) Registry {
config.Prefix = defaultMetricsPrefix config.Prefix = defaultMetricsPrefix
} }
statsdClient = statsd.New(config.Prefix+".", kitlog.LoggerFunc(func(keyvals ...interface{}) error { statsdClient = statsd.New(config.Prefix+".", kitlog.LoggerFunc(func(keyvals ...any) error {
log.WithoutContext().WithField(log.MetricsProviderName, "statsd").Info(keyvals...) log.WithoutContext().WithField(log.MetricsProviderName, "statsd").Info(keyvals...)
return nil return nil
})) }))
+1 -1
View File
@@ -121,7 +121,7 @@ func init() {
} }
// CoreLogData holds the fields computed from the request/response. // CoreLogData holds the fields computed from the request/response.
type CoreLogData map[string]interface{} type CoreLogData map[string]any
// LogData is the data captured by the middleware so that it can be logged. // LogData is the data captured by the middleware so that it can be logged.
type LogData struct { type LogData struct {
@@ -52,7 +52,7 @@ func (f *CommonLogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
return b.Bytes(), err return b.Bytes(), err
} }
func toLog(fields logrus.Fields, key, defaultValue string, quoted bool) interface{} { func toLog(fields logrus.Fields, key, defaultValue string, quoted bool) any {
if v, ok := fields[key]; ok { if v, ok := fields[key]; ok {
if v == nil { if v == nil {
return defaultValue return defaultValue
@@ -14,12 +14,12 @@ func TestCommonLogFormatter_Format(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
data map[string]interface{} data map[string]any
expectedLog string expectedLog string
}{ }{
{ {
name: "DownstreamStatus & DownstreamContentSize are nil", name: "DownstreamStatus & DownstreamContentSize are nil",
data: map[string]interface{}{ data: map[string]any{
StartUTC: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), StartUTC: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC),
Duration: 123 * time.Second, Duration: 123 * time.Second,
ClientHost: "10.0.0.1", ClientHost: "10.0.0.1",
@@ -40,7 +40,7 @@ func TestCommonLogFormatter_Format(t *testing.T) {
}, },
{ {
name: "all data", name: "all data",
data: map[string]interface{}{ data: map[string]any{
StartUTC: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), StartUTC: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC),
Duration: 123 * time.Second, Duration: 123 * time.Second,
ClientHost: "10.0.0.1", ClientHost: "10.0.0.1",
@@ -61,7 +61,7 @@ func TestCommonLogFormatter_Format(t *testing.T) {
}, },
{ {
name: "all data with local time", name: "all data with local time",
data: map[string]interface{}{ data: map[string]any{
StartLocal: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), StartLocal: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC),
Duration: 123 * time.Second, Duration: 123 * time.Second,
ClientHost: "10.0.0.1", ClientHost: "10.0.0.1",
@@ -106,7 +106,7 @@ func Test_toLog(t *testing.T) {
fieldName string fieldName string
defaultValue string defaultValue string
quoted bool quoted bool
expectedLog interface{} expectedLog any
}{ }{
{ {
desc: "Should return int 1", desc: "Should return int 1",
+20 -20
View File
@@ -116,7 +116,7 @@ func lineCount(t *testing.T, fileName string) int {
} }
count := 0 count := 0
for _, line := range strings.Split(string(fileContents), "\n") { for line := range strings.SplitSeq(string(fileContents), "\n") {
if strings.TrimSpace(line) == "" { if strings.TrimSpace(line) == "" {
continue continue
} }
@@ -259,32 +259,32 @@ func TestLoggerCLFWithBufferingSize(t *testing.T) {
assertValidLogData(t, expectedLog, logData) assertValidLogData(t, expectedLog, logData)
} }
func assertString(exp string) func(t *testing.T, actual interface{}) { func assertString(exp string) func(t *testing.T, actual any) {
return func(t *testing.T, actual interface{}) { return func(t *testing.T, actual any) {
t.Helper() t.Helper()
assert.Equal(t, exp, actual) assert.Equal(t, exp, actual)
} }
} }
func assertNotEmpty() func(t *testing.T, actual interface{}) { func assertNotEmpty() func(t *testing.T, actual any) {
return func(t *testing.T, actual interface{}) { return func(t *testing.T, actual any) {
t.Helper() t.Helper()
assert.NotEmpty(t, actual) assert.NotEmpty(t, actual)
} }
} }
func assertFloat64(exp float64) func(t *testing.T, actual interface{}) { func assertFloat64(exp float64) func(t *testing.T, actual any) {
return func(t *testing.T, actual interface{}) { return func(t *testing.T, actual any) {
t.Helper() t.Helper()
assert.InDelta(t, exp, actual, delta) assert.InDelta(t, exp, actual, delta)
} }
} }
func assertFloat64NotZero() func(t *testing.T, actual interface{}) { func assertFloat64NotZero() func(t *testing.T, actual any) {
return func(t *testing.T, actual interface{}) { return func(t *testing.T, actual any) {
t.Helper() t.Helper()
assert.NotZero(t, actual) assert.NotZero(t, actual)
@@ -296,7 +296,7 @@ func TestLoggerJSON(t *testing.T) {
desc string desc string
config *types.AccessLog config *types.AccessLog
tls bool tls bool
expected map[string]func(t *testing.T, value interface{}) expected map[string]func(t *testing.T, value any)
}{ }{
{ {
desc: "default config", desc: "default config",
@@ -304,7 +304,7 @@ func TestLoggerJSON(t *testing.T) {
FilePath: "", FilePath: "",
Format: JSONFormat, Format: JSONFormat,
}, },
expected: map[string]func(t *testing.T, value interface{}){ expected: map[string]func(t *testing.T, value any){
RequestContentSize: assertFloat64(0), RequestContentSize: assertFloat64(0),
RequestHost: assertString(testHostname), RequestHost: assertString(testHostname),
RequestAddr: assertString(testHostname), RequestAddr: assertString(testHostname),
@@ -344,7 +344,7 @@ func TestLoggerJSON(t *testing.T) {
Format: JSONFormat, Format: JSONFormat,
}, },
tls: true, tls: true,
expected: map[string]func(t *testing.T, value interface{}){ expected: map[string]func(t *testing.T, value any){
RequestContentSize: assertFloat64(0), RequestContentSize: assertFloat64(0),
RequestHost: assertString(testHostname), RequestHost: assertString(testHostname),
RequestAddr: assertString(testHostname), RequestAddr: assertString(testHostname),
@@ -388,7 +388,7 @@ func TestLoggerJSON(t *testing.T) {
DefaultMode: "drop", DefaultMode: "drop",
}, },
}, },
expected: map[string]func(t *testing.T, value interface{}){ expected: map[string]func(t *testing.T, value any){
"level": assertString("info"), "level": assertString("info"),
"msg": assertString(""), "msg": assertString(""),
"time": assertNotEmpty(), "time": assertNotEmpty(),
@@ -409,7 +409,7 @@ func TestLoggerJSON(t *testing.T) {
}, },
}, },
}, },
expected: map[string]func(t *testing.T, value interface{}){ expected: map[string]func(t *testing.T, value any){
"level": assertString("info"), "level": assertString("info"),
"msg": assertString(""), "msg": assertString(""),
"time": assertNotEmpty(), "time": assertNotEmpty(),
@@ -427,7 +427,7 @@ func TestLoggerJSON(t *testing.T) {
}, },
}, },
}, },
expected: map[string]func(t *testing.T, value interface{}){ expected: map[string]func(t *testing.T, value any){
"level": assertString("info"), "level": assertString("info"),
"msg": assertString(""), "msg": assertString(""),
"time": assertNotEmpty(), "time": assertNotEmpty(),
@@ -454,7 +454,7 @@ func TestLoggerJSON(t *testing.T) {
}, },
}, },
}, },
expected: map[string]func(t *testing.T, value interface{}){ expected: map[string]func(t *testing.T, value any){
RequestHost: assertString(testHostname), RequestHost: assertString(testHostname),
"level": assertString("info"), "level": assertString("info"),
"msg": assertString(""), "msg": assertString(""),
@@ -480,7 +480,7 @@ func TestLoggerJSON(t *testing.T) {
}, },
}, },
}, },
expected: map[string]func(t *testing.T, value interface{}){ expected: map[string]func(t *testing.T, value any){
RequestHost: assertString(testHostname), RequestHost: assertString(testHostname),
"level": assertString("info"), "level": assertString("info"),
"msg": assertString(""), "msg": assertString(""),
@@ -506,7 +506,7 @@ func TestLoggerJSON(t *testing.T) {
logData, err := os.ReadFile(logFilePath) logData, err := os.ReadFile(logFilePath)
require.NoError(t, err) require.NoError(t, err)
jsonData := make(map[string]interface{}) jsonData := make(map[string]any)
err = json.Unmarshal(logData, &jsonData) err = json.Unmarshal(logData, &jsonData)
require.NoError(t, err) require.NoError(t, err)
@@ -520,7 +520,7 @@ func TestLoggerJSON(t *testing.T) {
} }
func TestLogger_AbortedRequest(t *testing.T) { func TestLogger_AbortedRequest(t *testing.T) {
expected := map[string]func(t *testing.T, value interface{}){ expected := map[string]func(t *testing.T, value any){
RequestContentSize: assertFloat64(0), RequestContentSize: assertFloat64(0),
RequestHost: assertString(testHostname), RequestHost: assertString(testHostname),
RequestAddr: assertString(testHostname), RequestAddr: assertString(testHostname),
@@ -563,7 +563,7 @@ func TestLogger_AbortedRequest(t *testing.T) {
logData, err := os.ReadFile(config.FilePath) logData, err := os.ReadFile(config.FilePath)
require.NoError(t, err) require.NoError(t, err)
jsonData := make(map[string]interface{}) jsonData := make(map[string]any)
err = json.Unmarshal(logData, &jsonData) err = json.Unmarshal(logData, &jsonData)
require.NoError(t, err) require.NoError(t, err)
+1 -1
View File
@@ -22,7 +22,7 @@ func RemoveConnectionHeaders(req *http.Request) {
} }
for _, f := range req.Header[connectionHeader] { for _, f := range req.Header[connectionHeader] {
for _, sf := range strings.Split(f, ",") { for sf := range strings.SplitSeq(f, ",") {
if sf = textproto.TrimString(sf); sf != "" { if sf = textproto.TrimString(sf); sf != "" {
req.Header.Del(sf) req.Header.Del(sf)
} }
+14 -14
View File
@@ -84,20 +84,6 @@ func (c *Capture) Reset(next http.Handler) http.Handler {
}) })
} }
func (c *Capture) renew(rw http.ResponseWriter, req *http.Request) (http.ResponseWriter, *http.Request) {
ctx := context.WithValue(req.Context(), capturedData, c)
newReq := req.WithContext(ctx)
if newReq.Body != nil {
readCounter := &readCounter{source: newReq.Body}
c.rr = readCounter
newReq.Body = readCounter
}
c.rw = newResponseWriter(rw)
return c.rw, newReq
}
func (c *Capture) ResponseSize() int64 { func (c *Capture) ResponseSize() int64 {
return c.rw.Size() return c.rw.Size()
} }
@@ -115,6 +101,20 @@ func (c *Capture) RequestSize() int64 {
return c.rr.size return c.rr.size
} }
func (c *Capture) renew(rw http.ResponseWriter, req *http.Request) (http.ResponseWriter, *http.Request) {
ctx := context.WithValue(req.Context(), capturedData, c)
newReq := req.WithContext(ctx)
if newReq.Body != nil {
readCounter := &readCounter{source: newReq.Body}
c.rr = readCounter
newReq.Body = readCounter
}
c.rw = newResponseWriter(rw)
return c.rw, newReq
}
type readCounter struct { type readCounter struct {
// source ReadCloser from where the request body is read. // source ReadCloser from where the request body is read.
source io.ReadCloser source io.ReadCloser
+17 -22
View File
@@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"context" "context"
"fmt" "fmt"
"maps"
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
@@ -169,16 +170,6 @@ func (cc *codeCatcher) Header() http.Header {
return cc.headerMap return cc.headerMap
} }
func (cc *codeCatcher) getCode() int {
return cc.code
}
// isFilteredCode returns whether the codeCatcher received a response code among the ones it is watching,
// and for which the response should be deferred to the error handler.
func (cc *codeCatcher) isFilteredCode() bool {
return cc.caughtFilteredCode
}
func (cc *codeCatcher) Write(buf []byte) (int, error) { func (cc *codeCatcher) Write(buf []byte) (int, error) {
// If WriteHeader was already called from the caller, this is a NOOP. // If WriteHeader was already called from the caller, this is a NOOP.
// Otherwise, cc.code is actually a 200 here. // Otherwise, cc.code is actually a 200 here.
@@ -204,9 +195,7 @@ func (cc *codeCatcher) WriteHeader(code int) {
if code >= 100 && code <= 199 { if code >= 100 && code <= 199 {
// Multiple informational status codes can be used, // Multiple informational status codes can be used,
// so here the copy is not appending the values to not repeat them. // so here the copy is not appending the values to not repeat them.
for k, v := range cc.Header() { maps.Copy(cc.responseWriter.Header(), cc.Header())
cc.responseWriter.Header()[k] = v
}
cc.responseWriter.WriteHeader(code) cc.responseWriter.WriteHeader(code)
return return
@@ -224,9 +213,8 @@ func (cc *codeCatcher) WriteHeader(code int) {
// The copy is not appending the values, // The copy is not appending the values,
// to not repeat them in case any informational status code has been written. // to not repeat them in case any informational status code has been written.
for k, v := range cc.Header() { maps.Copy(cc.responseWriter.Header(), cc.Header())
cc.responseWriter.Header()[k] = v
}
cc.responseWriter.WriteHeader(cc.code) cc.responseWriter.WriteHeader(cc.code)
cc.headersSent = true cc.headersSent = true
} }
@@ -259,6 +247,16 @@ func (cc *codeCatcher) Flush() {
} }
} }
func (cc *codeCatcher) getCode() int {
return cc.code
}
// isFilteredCode returns whether the codeCatcher received a response code among the ones it is watching,
// and for which the response should be deferred to the error handler.
func (cc *codeCatcher) isFilteredCode() bool {
return cc.caughtFilteredCode
}
type codeCatcherWithCloseNotify struct { type codeCatcherWithCloseNotify struct {
*codeCatcher *codeCatcher
} }
@@ -332,17 +330,14 @@ func (r *codeModifierWithoutCloseNotify) WriteHeader(code int) {
if code >= 100 && code <= 199 { if code >= 100 && code <= 199 {
// Multiple informational status codes can be used, // Multiple informational status codes can be used,
// so here the copy is not appending the values to not repeat them. // so here the copy is not appending the values to not repeat them.
for k, v := range r.headerMap { maps.Copy(r.responseWriter.Header(), r.headerMap)
r.responseWriter.Header()[k] = v
}
r.responseWriter.WriteHeader(code) r.responseWriter.WriteHeader(code)
return return
} }
for k, v := range r.headerMap { maps.Copy(r.responseWriter.Header(), r.headerMap)
r.responseWriter.Header()[k] = v
}
r.responseWriter.WriteHeader(r.code) r.responseWriter.WriteHeader(r.code)
r.headerSent = true r.headerSent = true
} }
@@ -81,13 +81,6 @@ func NewXForwarded(insecure bool, trustedIPs []string, connectionHeaders []strin
}, nil }, nil
} }
func (x *XForwarded) isTrustedIP(ip string) bool {
if x.ipChecker == nil {
return false
}
return x.ipChecker.IsAuthorized(ip) == nil
}
// removeIPv6Zone removes the zone if the given IP is an ipv6 address and it has {zone} information in it, // removeIPv6Zone removes the zone if the given IP is an ipv6 address and it has {zone} information in it,
// like "[fe80::d806:a55d:eb1b:49cc%vEthernet (vmxnet3 Ethernet Adapter - Virtual Switch)]:64692". // like "[fe80::d806:a55d:eb1b:49cc%vEthernet (vmxnet3 Ethernet Adapter - Virtual Switch)]:64692".
func removeIPv6Zone(clientIP string) string { func removeIPv6Zone(clientIP string) string {
@@ -138,6 +131,28 @@ func forwardedPort(req *http.Request) string {
return "80" return "80"
} }
// ServeHTTP implements http.Handler.
func (x *XForwarded) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if !x.insecure && !x.isTrustedIP(r.RemoteAddr) {
for _, h := range xHeaders {
unsafeHeader(r.Header).Del(h)
}
}
x.rewrite(r)
x.removeConnectionHeaders(r)
x.next.ServeHTTP(w, r)
}
func (x *XForwarded) isTrustedIP(ip string) bool {
if x.ipChecker == nil {
return false
}
return x.ipChecker.IsAuthorized(ip) == nil
}
func (x *XForwarded) rewrite(outreq *http.Request) { func (x *XForwarded) rewrite(outreq *http.Request) {
if clientIP, _, err := net.SplitHostPort(outreq.RemoteAddr); err == nil { if clientIP, _, err := net.SplitHostPort(outreq.RemoteAddr); err == nil {
clientIP = removeIPv6Zone(clientIP) clientIP = removeIPv6Zone(clientIP)
@@ -186,21 +201,6 @@ func (x *XForwarded) rewrite(outreq *http.Request) {
} }
} }
// ServeHTTP implements http.Handler.
func (x *XForwarded) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if !x.insecure && !x.isTrustedIP(r.RemoteAddr) {
for _, h := range xHeaders {
unsafeHeader(r.Header).Del(h)
}
}
x.rewrite(r)
x.removeConnectionHeaders(r)
x.next.ServeHTTP(w, r)
}
func (x *XForwarded) removeConnectionHeaders(req *http.Request) { func (x *XForwarded) removeConnectionHeaders(req *http.Request) {
var reqUpType string var reqUpType string
if httpguts.HeaderValuesContainsToken(req.Header[connection], upgrade) { if httpguts.HeaderValuesContainsToken(req.Header[connection], upgrade) {
@@ -209,7 +209,7 @@ func (x *XForwarded) removeConnectionHeaders(req *http.Request) {
var connectionHopByHopHeaders []string var connectionHopByHopHeaders []string
for _, f := range req.Header[connection] { for _, f := range req.Header[connection] {
for _, sf := range strings.Split(f, ",") { for sf := range strings.SplitSeq(f, ",") {
if sf = textproto.TrimString(sf); sf != "" { if sf = textproto.TrimString(sf); sf != "" {
// Connection header cannot dictate to remove X- headers managed by Traefik, // Connection header cannot dictate to remove X- headers managed by Traefik,
// as per rfc7230 https://datatracker.ietf.org/doc/html/rfc7230#section-6.1, // as per rfc7230 https://datatracker.ietf.org/doc/html/rfc7230#section-6.1,
+21 -21
View File
@@ -68,27 +68,6 @@ func (s *Header) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
} }
} }
// modifyCustomRequestHeaders sets or deletes custom request headers.
func (s *Header) modifyCustomRequestHeaders(req *http.Request) {
// Loop through Custom request headers
for header, value := range s.headers.CustomRequestHeaders {
switch {
// Handling https://github.com/golang/go/commit/ecdbffd4ec68b509998792f120868fec319de59b.
case value == "" && header == forward.XForwardedFor:
req.Header[header] = nil
case value == "":
req.Header.Del(header)
case strings.EqualFold(header, "Host"):
req.Host = value
default:
req.Header.Set(header, value)
}
}
}
// PostRequestModifyResponseHeaders set or delete response headers. // PostRequestModifyResponseHeaders set or delete response headers.
// This method is called AFTER the response is generated from the backend // This method is called AFTER the response is generated from the backend
// and can merge/override headers from the backend response. // and can merge/override headers from the backend response.
@@ -138,6 +117,27 @@ func (s *Header) PostRequestModifyResponseHeaders(res *http.Response) error {
return nil return nil
} }
// modifyCustomRequestHeaders sets or deletes custom request headers.
func (s *Header) modifyCustomRequestHeaders(req *http.Request) {
// Loop through Custom request headers
for header, value := range s.headers.CustomRequestHeaders {
switch {
// Handling https://github.com/golang/go/commit/ecdbffd4ec68b509998792f120868fec319de59b.
case value == "" && header == forward.XForwardedFor:
req.Header[header] = nil
case value == "":
req.Header.Del(header)
case strings.EqualFold(header, "Host"):
req.Host = value
default:
req.Header.Set(header, value)
}
}
}
// processCorsHeaders processes the incoming request, // processCorsHeaders processes the incoming request,
// and returns if it is a preflight request. // and returns if it is a preflight request.
// If not a preflight, it handles the preRequestModifyCorsResponseHeaders. // If not a preflight, it handles the preRequestModifyCorsResponseHeaders.
+2 -1
View File
@@ -18,10 +18,11 @@ func Test_newSecure_sslForceHost(t *testing.T) {
} }
testCases := []struct { testCases := []struct {
expected
desc string desc string
host string host string
cfg dynamic.Headers cfg dynamic.Headers
expected
}{ }{
{ {
desc: "http should return a 301", desc: "http should return a 301",
+5 -4
View File
@@ -27,6 +27,7 @@ func newResponseRecorder(rw http.ResponseWriter) recorder {
// later analysis. // later analysis.
type responseRecorder struct { type responseRecorder struct {
http.ResponseWriter http.ResponseWriter
statusCode int statusCode int
} }
@@ -40,10 +41,6 @@ func (r *responseRecorderWithCloseNotify) CloseNotify() <-chan bool {
return r.ResponseWriter.(http.CloseNotifier).CloseNotify() return r.ResponseWriter.(http.CloseNotifier).CloseNotify()
} }
func (r *responseRecorder) getCode() int {
return r.statusCode
}
// WriteHeader captures the status code for later retrieval. // WriteHeader captures the status code for later retrieval.
func (r *responseRecorder) WriteHeader(status int) { func (r *responseRecorder) WriteHeader(status int) {
r.ResponseWriter.WriteHeader(status) r.ResponseWriter.WriteHeader(status)
@@ -61,3 +58,7 @@ func (r *responseRecorder) Flush() {
f.Flush() f.Flush()
} }
} }
func (r *responseRecorder) getCode() int {
return r.statusCode
}
+1 -4
View File
@@ -66,10 +66,7 @@ func New(ctx context.Context, next http.Handler, config dynamic.RateLimit, name
return nil, err return nil, err
} }
burst := config.Burst burst := max(config.Burst, 1)
if burst < 1 {
burst = 1
}
period := time.Duration(config.Period) period := time.Duration(config.Period)
if period < 0 { if period < 0 {
@@ -283,11 +283,8 @@ func TestRateLimit(t *testing.T) {
stop := time.Now() stop := time.Now()
elapsed := stop.Sub(start) elapsed := stop.Sub(start)
burst := test.config.Burst // actual default value if burst < 1
if burst < 1 { burst := max(test.config.Burst, 1)
// actual default value
burst = 1
}
period := time.Duration(test.config.Period) period := time.Duration(test.config.Period)
if period == 0 { if period == 0 {
+1 -1
View File
@@ -57,7 +57,7 @@ func recoverFunc(rw recoveryResponseWriter, r *http.Request) {
// https://github.com/golang/go/blob/a0d6420d8be2ae7164797051ec74fa2a2df466a1/src/net/http/server.go#L1761-L1775 // https://github.com/golang/go/blob/a0d6420d8be2ae7164797051ec74fa2a2df466a1/src/net/http/server.go#L1761-L1775
// https://github.com/golang/go/blob/c33153f7b416c03983324b3e8f869ce1116d84bc/src/net/http/httputil/reverseproxy.go#L284 // https://github.com/golang/go/blob/c33153f7b416c03983324b3e8f869ce1116d84bc/src/net/http/httputil/reverseproxy.go#L284
func shouldLogPanic(panicValue interface{}) bool { func shouldLogPanic(panicValue any) bool {
//nolint:errorlint // false-positive because panicValue is an interface. //nolint:errorlint // false-positive because panicValue is an interface.
return panicValue != nil && panicValue != http.ErrAbortHandler return panicValue != nil && panicValue != http.ErrAbortHandler
} }
+2 -4
View File
@@ -5,6 +5,7 @@ import (
"context" "context"
"fmt" "fmt"
"io" "io"
"maps"
"math" "math"
"net" "net"
"net/http" "net/http"
@@ -239,10 +240,7 @@ func (r *responseWriterWithoutCloseNotify) WriteHeader(code int) {
// to write headers to the backend : we are not going to perform any further retry. // to write headers to the backend : we are not going to perform any further retry.
// So it is now safe to alter current response headers with headers collected during // So it is now safe to alter current response headers with headers collected during
// the latest try before writing headers to client. // the latest try before writing headers to client.
headers := r.responseWriter.Header() maps.Copy(r.responseWriter.Header(), r.headers)
for header, value := range r.headers {
headers[header] = value
}
r.responseWriter.WriteHeader(code) r.responseWriter.WriteHeader(code)
+1
View File
@@ -29,6 +29,7 @@ func NewEntryPoint(ctx context.Context, t *tracing.Tracing, entryPointName strin
type entryPointMiddleware struct { type entryPointMiddleware struct {
*tracing.Tracing *tracing.Tracing
entryPoint string entryPoint string
next http.Handler next http.Handler
} }
+5 -5
View File
@@ -13,7 +13,7 @@ import (
func TestEntryPointMiddleware(t *testing.T) { func TestEntryPointMiddleware(t *testing.T) {
type expected struct { type expected struct {
Tags map[string]interface{} Tags map[string]any
OperationName string OperationName string
} }
@@ -29,10 +29,10 @@ func TestEntryPointMiddleware(t *testing.T) {
entryPoint: "test", entryPoint: "test",
spanNameLimit: 0, spanNameLimit: 0,
tracing: &trackingBackenMock{ tracing: &trackingBackenMock{
tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]any)}},
}, },
expected: expected{ expected: expected{
Tags: map[string]interface{}{ Tags: map[string]any{
"span.kind": ext.SpanKindRPCServerEnum, "span.kind": ext.SpanKindRPCServerEnum,
"http.method": http.MethodGet, "http.method": http.MethodGet,
"component": "", "component": "",
@@ -47,10 +47,10 @@ func TestEntryPointMiddleware(t *testing.T) {
entryPoint: "test", entryPoint: "test",
spanNameLimit: 25, spanNameLimit: 25,
tracing: &trackingBackenMock{ tracing: &trackingBackenMock{
tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]any)}},
}, },
expected: expected{ expected: expected{
Tags: map[string]interface{}{ Tags: map[string]any{
"span.kind": ext.SpanKindRPCServerEnum, "span.kind": ext.SpanKindRPCServerEnum,
"http.method": http.MethodGet, "http.method": http.MethodGet,
"component": "", "component": "",
+9 -9
View File
@@ -13,7 +13,7 @@ import (
func TestNewForwarder(t *testing.T) { func TestNewForwarder(t *testing.T) {
type expected struct { type expected struct {
Tags map[string]interface{} Tags map[string]any
OperationName string OperationName string
} }
@@ -29,12 +29,12 @@ func TestNewForwarder(t *testing.T) {
desc: "Simple Forward Tracer without truncation and hashing", desc: "Simple Forward Tracer without truncation and hashing",
spanNameLimit: 101, spanNameLimit: 101,
tracing: &trackingBackenMock{ tracing: &trackingBackenMock{
tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]any)}},
}, },
service: "some-service.domain.tld", service: "some-service.domain.tld",
router: "some-service.domain.tld", router: "some-service.domain.tld",
expected: expected{ expected: expected{
Tags: map[string]interface{}{ Tags: map[string]any{
"http.host": "www.test.com", "http.host": "www.test.com",
"http.method": "GET", "http.method": "GET",
"http.url": "http://www.test.com/toto", "http.url": "http://www.test.com/toto",
@@ -49,12 +49,12 @@ func TestNewForwarder(t *testing.T) {
desc: "Simple Forward Tracer with truncation and hashing", desc: "Simple Forward Tracer with truncation and hashing",
spanNameLimit: 101, spanNameLimit: 101,
tracing: &trackingBackenMock{ tracing: &trackingBackenMock{
tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]any)}},
}, },
service: "some-service-100.slug.namespace.environment.domain.tld", service: "some-service-100.slug.namespace.environment.domain.tld",
router: "some-service-100.slug.namespace.environment.domain.tld", router: "some-service-100.slug.namespace.environment.domain.tld",
expected: expected{ expected: expected{
Tags: map[string]interface{}{ Tags: map[string]any{
"http.host": "www.test.com", "http.host": "www.test.com",
"http.method": "GET", "http.method": "GET",
"http.url": "http://www.test.com/toto", "http.url": "http://www.test.com/toto",
@@ -69,12 +69,12 @@ func TestNewForwarder(t *testing.T) {
desc: "Exactly 101 chars", desc: "Exactly 101 chars",
spanNameLimit: 101, spanNameLimit: 101,
tracing: &trackingBackenMock{ tracing: &trackingBackenMock{
tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]any)}},
}, },
service: "some-service1.namespace.environment.domain.tld", service: "some-service1.namespace.environment.domain.tld",
router: "some-service1.namespace.environment.domain.tld", router: "some-service1.namespace.environment.domain.tld",
expected: expected{ expected: expected{
Tags: map[string]interface{}{ Tags: map[string]any{
"http.host": "www.test.com", "http.host": "www.test.com",
"http.method": "GET", "http.method": "GET",
"http.url": "http://www.test.com/toto", "http.url": "http://www.test.com/toto",
@@ -89,12 +89,12 @@ func TestNewForwarder(t *testing.T) {
desc: "More than 101 chars", desc: "More than 101 chars",
spanNameLimit: 101, spanNameLimit: 101,
tracing: &trackingBackenMock{ tracing: &trackingBackenMock{
tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]any)}},
}, },
service: "some-service1.frontend.namespace.environment.domain.tld", service: "some-service1.frontend.namespace.environment.domain.tld",
router: "some-service1.backend.namespace.environment.domain.tld", router: "some-service1.backend.namespace.environment.domain.tld",
expected: expected{ expected: expected{
Tags: map[string]interface{}{ Tags: map[string]any{
"http.host": "www.test.com", "http.host": "www.test.com",
"http.method": "GET", "http.method": "GET",
"http.url": "http://www.test.com/toto", "http.url": "http://www.test.com/toto",
+8 -8
View File
@@ -18,12 +18,12 @@ func (n MockTracer) StartSpan(operationName string, opts ...opentracing.StartSpa
} }
// Inject belongs to the Tracer interface. // Inject belongs to the Tracer interface.
func (n MockTracer) Inject(sp opentracing.SpanContext, format, carrier interface{}) error { func (n MockTracer) Inject(sp opentracing.SpanContext, format, carrier any) error {
return nil return nil
} }
// Extract belongs to the Tracer interface. // Extract belongs to the Tracer interface.
func (n MockTracer) Extract(format, carrier interface{}) (opentracing.SpanContext, error) { func (n MockTracer) Extract(format, carrier any) (opentracing.SpanContext, error) {
return nil, opentracing.ErrSpanContextNotFound return nil, opentracing.ErrSpanContextNotFound
} }
@@ -35,29 +35,29 @@ func (n MockSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {}
// MockSpan a span mock. // MockSpan a span mock.
type MockSpan struct { type MockSpan struct {
OpName string OpName string
Tags map[string]interface{} Tags map[string]any
} }
func (n *MockSpan) Context() opentracing.SpanContext { return MockSpanContext{} } func (n *MockSpan) Context() opentracing.SpanContext { return MockSpanContext{} }
func (n *MockSpan) SetBaggageItem(key, val string) opentracing.Span { func (n *MockSpan) SetBaggageItem(key, val string) opentracing.Span {
return &MockSpan{Tags: make(map[string]interface{})} return &MockSpan{Tags: make(map[string]any)}
} }
func (n *MockSpan) BaggageItem(key string) string { return "" } func (n *MockSpan) BaggageItem(key string) string { return "" }
func (n *MockSpan) SetTag(key string, value interface{}) opentracing.Span { func (n *MockSpan) SetTag(key string, value any) opentracing.Span {
n.Tags[key] = value n.Tags[key] = value
return n return n
} }
func (n *MockSpan) LogFields(fields ...log.Field) {} func (n *MockSpan) LogFields(fields ...log.Field) {}
func (n *MockSpan) LogKV(keyVals ...interface{}) {} func (n *MockSpan) LogKV(keyVals ...any) {}
func (n *MockSpan) Finish() {} func (n *MockSpan) Finish() {}
func (n *MockSpan) FinishWithOptions(opts opentracing.FinishOptions) {} func (n *MockSpan) FinishWithOptions(opts opentracing.FinishOptions) {}
func (n *MockSpan) SetOperationName(operationName string) opentracing.Span { return n } func (n *MockSpan) SetOperationName(operationName string) opentracing.Span { return n }
func (n *MockSpan) Tracer() opentracing.Tracer { return MockTracer{} } func (n *MockSpan) Tracer() opentracing.Tracer { return MockTracer{} }
func (n *MockSpan) LogEvent(event string) {} func (n *MockSpan) LogEvent(event string) {}
func (n *MockSpan) LogEventWithPayload(event string, payload interface{}) {} func (n *MockSpan) LogEventWithPayload(event string, payload any) {}
func (n *MockSpan) Log(data opentracing.LogData) {} func (n *MockSpan) Log(data opentracing.LogData) {}
func (n *MockSpan) Reset() { func (n *MockSpan) Reset() {
n.Tags = make(map[string]interface{}) n.Tags = make(map[string]any)
} }
type trackingBackenMock struct { type trackingBackenMock struct {
+1
View File
@@ -22,6 +22,7 @@ func newStatusCodeRecoder(rw http.ResponseWriter, status int) statusCodeRecoder
type statusCodeWithoutCloseNotify struct { type statusCodeWithoutCloseNotify struct {
http.ResponseWriter http.ResponseWriter
status int status int
} }
+1
View File
@@ -32,6 +32,7 @@ var httpFuncs = map[string]func(*mux.Route, ...string) error{
// Muxer handles routing with rules. // Muxer handles routing with rules.
type Muxer struct { type Muxer struct {
*mux.Router *mux.Router
parser predicate.Parser parser predicate.Parser
} }
+29 -29
View File
@@ -245,35 +245,6 @@ func (c *Client) Unzip(pName, pVersion string) error {
return c.unzipArchive(pName, pVersion) return c.unzipArchive(pName, pVersion)
} }
func (c *Client) unzipModule(pName, pVersion string) error {
src := c.buildArchivePath(pName, pVersion)
dest := filepath.Join(c.sources, filepath.FromSlash(pName))
return zip.Unzip(dest, module.Version{Path: pName, Version: pVersion}, src)
}
func (c *Client) unzipArchive(pName, pVersion string) error {
zipPath := c.buildArchivePath(pName, pVersion)
archive, err := zipa.OpenReader(zipPath)
if err != nil {
return err
}
defer func() { _ = archive.Close() }()
dest := filepath.Join(c.sources, filepath.FromSlash(pName))
for _, f := range archive.File {
err = unzipFile(f, dest)
if err != nil {
return fmt.Errorf("unable to unzip %s: %w", f.Name, err)
}
}
return nil
}
func unzipFile(f *zipa.File, dest string) error { func unzipFile(f *zipa.File, dest string) error {
rc, err := f.Open() rc, err := f.Open()
if err != nil { if err != nil {
@@ -404,6 +375,35 @@ func (c *Client) ResetAll() error {
return nil return nil
} }
func (c *Client) unzipModule(pName, pVersion string) error {
src := c.buildArchivePath(pName, pVersion)
dest := filepath.Join(c.sources, filepath.FromSlash(pName))
return zip.Unzip(dest, module.Version{Path: pName, Version: pVersion}, src)
}
func (c *Client) unzipArchive(pName, pVersion string) error {
zipPath := c.buildArchivePath(pName, pVersion)
archive, err := zipa.OpenReader(zipPath)
if err != nil {
return err
}
defer func() { _ = archive.Close() }()
dest := filepath.Join(c.sources, filepath.FromSlash(pName))
for _, f := range archive.File {
err = unzipFile(f, dest)
if err != nil {
return fmt.Errorf("unable to unzip %s: %w", f.Name, err)
}
}
return nil
}
func (c *Client) buildArchivePath(pName, pVersion string) string { func (c *Client) buildArchivePath(pName, pVersion string) string {
return filepath.Join(c.archives, filepath.FromSlash(pName), pVersion+".zip") return filepath.Join(c.archives, filepath.FromSlash(pName), pVersion+".zip")
} }
+3 -3
View File
@@ -13,7 +13,7 @@ import (
) )
// Build builds a middleware plugin. // Build builds a middleware plugin.
func (b Builder) Build(pName string, config map[string]interface{}, middlewareName string) (Constructor, error) { func (b Builder) Build(pName string, config map[string]any, middlewareName string) (Constructor, error) {
if b.middlewareBuilders == nil { if b.middlewareBuilders == nil {
return nil, fmt.Errorf("no plugin definition in the static configuration: %s", pName) return nil, fmt.Errorf("no plugin definition in the static configuration: %s", pName)
} }
@@ -77,7 +77,7 @@ func (p middlewareBuilder) newHandler(ctx context.Context, next http.Handler, cf
return handler, nil return handler, nil
} }
func (p middlewareBuilder) createConfig(config map[string]interface{}) (reflect.Value, error) { func (p middlewareBuilder) createConfig(config map[string]any) (reflect.Value, error) {
results := p.fnCreateConfig.Call(nil) results := p.fnCreateConfig.Call(nil)
if len(results) != 1 { if len(results) != 1 {
return reflect.Value{}, fmt.Errorf("invalid number of return for the CreateConfig function: %d", len(results)) return reflect.Value{}, fmt.Errorf("invalid number of return for the CreateConfig function: %d", len(results))
@@ -114,7 +114,7 @@ type Middleware struct {
builder *middlewareBuilder builder *middlewareBuilder
} }
func newMiddleware(builder *middlewareBuilder, config map[string]interface{}, middlewareName string) (*Middleware, error) { func newMiddleware(builder *middlewareBuilder, config map[string]any, middlewareName string) (*Middleware, error) {
vConfig, err := builder.createConfig(config) vConfig, err := builder.createConfig(config)
if err != nil { if err != nil {
return nil, err return nil, err
+3 -3
View File
@@ -24,7 +24,7 @@ type PP interface {
} }
type _PP struct { type _PP struct {
IValue interface{} IValue any
WInit func() error WInit func() error
WProvide func(cfgChan chan<- json.Marshaler) error WProvide func(cfgChan chan<- json.Marshaler) error
WStop func() error WStop func() error
@@ -52,7 +52,7 @@ func ppSymbols() map[string]map[string]reflect.Value {
} }
// BuildProvider builds a plugin's provider. // BuildProvider builds a plugin's provider.
func (b Builder) BuildProvider(pName string, config map[string]interface{}) (provider.Provider, error) { func (b Builder) BuildProvider(pName string, config map[string]any) (provider.Provider, error) {
if b.providerBuilders == nil { if b.providerBuilders == nil {
return nil, fmt.Errorf("no plugin definition in the static configuration: %s", pName) return nil, fmt.Errorf("no plugin definition in the static configuration: %s", pName)
} }
@@ -81,7 +81,7 @@ type Provider struct {
pp PP pp PP
} }
func newProvider(builder providerBuilder, config map[string]interface{}, providerName string) (*Provider, error) { func newProvider(builder providerBuilder, config map[string]any, providerName string) (*Provider, error) {
basePkg := builder.BasePkg basePkg := builder.BasePkg
if basePkg == "" { if basePkg == "" {
basePkg = strings.ReplaceAll(path.Base(builder.Import), "-", "_") basePkg = strings.ReplaceAll(path.Base(builder.Import), "-", "_")
+7 -7
View File
@@ -17,11 +17,11 @@ type LocalDescriptor struct {
// Manifest The plugin manifest. // Manifest The plugin manifest.
type Manifest struct { type Manifest struct {
DisplayName string `yaml:"displayName"` DisplayName string `yaml:"displayName"`
Type string `yaml:"type"` Type string `yaml:"type"`
Import string `yaml:"import"` Import string `yaml:"import"`
BasePkg string `yaml:"basePkg"` BasePkg string `yaml:"basePkg"`
Compatibility string `yaml:"compatibility"` Compatibility string `yaml:"compatibility"`
Summary string `yaml:"summary"` Summary string `yaml:"summary"`
TestData map[string]interface{} `yaml:"testData"` TestData map[string]any `yaml:"testData"`
} }
+49 -53
View File
@@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"io" "io"
"maps"
"os" "os"
"sync" "sync"
@@ -29,6 +30,52 @@ func NewLocalStore(filename string, routinesPool *safe.Pool) *LocalStore {
return store return store
} }
// GetAccount returns ACME Account.
func (s *LocalStore) GetAccount(resolverName string) (*Account, error) {
storedData, err := s.get(resolverName)
if err != nil {
return nil, err
}
return storedData.Account, nil
}
// SaveAccount stores ACME Account.
func (s *LocalStore) SaveAccount(resolverName string, account *Account) error {
storedData, err := s.get(resolverName)
if err != nil {
return err
}
storedData.Account = account
s.save(resolverName, storedData)
return nil
}
// GetCertificates returns ACME Certificates list.
func (s *LocalStore) GetCertificates(resolverName string) ([]*CertAndStore, error) {
storedData, err := s.get(resolverName)
if err != nil {
return nil, err
}
return storedData.Certificates, nil
}
// SaveCertificates stores ACME Certificates list.
func (s *LocalStore) SaveCertificates(resolverName string, certificates []*CertAndStore) error {
storedData, err := s.get(resolverName)
if err != nil {
return err
}
storedData.Certificates = certificates
s.save(resolverName, storedData)
return nil
}
func (s *LocalStore) save(resolverName string, storedData *StoredData) { func (s *LocalStore) save(resolverName string, storedData *StoredData) {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
@@ -121,8 +168,7 @@ func (s *LocalStore) listenSaveAction(routinesPool *safe.Pool) {
logger.Error(err) logger.Error(err)
} }
err = os.WriteFile(s.filename, data, 0o600) if err := os.WriteFile(s.filename, data, 0o600); err != nil {
if err != nil {
logger.Error(err) logger.Error(err)
} }
} }
@@ -132,55 +178,5 @@ func (s *LocalStore) listenSaveAction(routinesPool *safe.Pool) {
// unSafeCopyOfStoredData creates maps copy of storedData. Is not thread safe, you should use `s.lock`. // unSafeCopyOfStoredData creates maps copy of storedData. Is not thread safe, you should use `s.lock`.
func (s *LocalStore) unSafeCopyOfStoredData() map[string]*StoredData { func (s *LocalStore) unSafeCopyOfStoredData() map[string]*StoredData {
result := map[string]*StoredData{} return maps.Clone(s.storedData)
for k, v := range s.storedData {
result[k] = v
}
return result
}
// GetAccount returns ACME Account.
func (s *LocalStore) GetAccount(resolverName string) (*Account, error) {
storedData, err := s.get(resolverName)
if err != nil {
return nil, err
}
return storedData.Account, nil
}
// SaveAccount stores ACME Account.
func (s *LocalStore) SaveAccount(resolverName string, account *Account) error {
storedData, err := s.get(resolverName)
if err != nil {
return err
}
storedData.Account = account
s.save(resolverName, storedData)
return nil
}
// GetCertificates returns ACME Certificates list.
func (s *LocalStore) GetCertificates(resolverName string) ([]*CertAndStore, error) {
storedData, err := s.get(resolverName)
if err != nil {
return nil, err
}
return storedData.Certificates, nil
}
// SaveCertificates stores ACME Certificates list.
func (s *LocalStore) SaveCertificates(resolverName string, certificates []*CertAndStore) error {
storedData, err := s.get(resolverName)
if err != nil {
return err
}
storedData.Certificates = certificates
s.save(resolverName, storedData)
return nil
} }

Some files were not shown because too many files have changed in this diff Show More