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:
GO_VERSION: '1.24'
GOLANGCI_LINT_VERSION: v2.0.2
MISSPELL_VERSION: v0.6.0
GOLANGCI_LINT_VERSION: v2.7.2
MISSPELL_VERSION: v0.7.0
jobs:
+20 -2
View File
@@ -36,6 +36,7 @@ linters:
- nilnil # Not relevant
- nlreturn # Not relevant
- noctx # Too strict
- noinlineerr # Too strict
- nonamedreturns # Too strict
- paralleltest # Not relevant
- prealloc # Too many false-positive.
@@ -47,6 +48,7 @@ linters:
- varnamelen # Not relevant
- wrapcheck # Too strict
- wsl # Too strict
- wsl_v5 # Too strict
settings:
depguard:
@@ -292,15 +294,31 @@ linters:
source: 'errors.New\("Nomad provider'
text: 'ST1005: error strings should not be capitalized'
- 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:
- revive
- 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:
- revive
- path: (.+)\.go$
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$
text: 'SA1019: cfg.(SSLRedirect|SSLTemporaryRedirect|SSLHost|SSLForceHost|FeaturePolicy) is deprecated'
- path: (.+)\.go$
+1
View File
@@ -10,6 +10,7 @@ import (
// TraefikCmdConfiguration wraps the static configuration and extra parameters.
type TraefikCmdConfiguration struct {
static.Configuration `export:"true"`
// ConfigFile is the path to the configuration file.
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 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 {
@@ -1273,6 +1273,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:
@@ -1663,8 +1664,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
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/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of
@@ -1907,6 +1909,7 @@ spec:
description: |-
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.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:
@@ -3703,6 +3706,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:
@@ -4093,8 +4097,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
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/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of
@@ -4337,6 +4342,7 @@ spec:
description: |-
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.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:
@@ -658,6 +658,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:
@@ -68,8 +68,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
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/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of
@@ -99,6 +99,7 @@ spec:
description: |-
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.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:
@@ -658,6 +658,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:
@@ -68,8 +68,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
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/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of
@@ -99,6 +99,7 @@ spec:
description: |-
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.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:
+1 -1
View File
@@ -28,7 +28,7 @@ theme:
prev: 'Previous'
next: 'Next'
copyright: 'Traefik Labs • Copyright © 2016-2025'
copyright: 'Traefik Labs • Copyright © 2016-2026'
extra_javascript:
- 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{}
if len(resp.Header["Www-Authenticate"]) > 0 {
wantedHeaders := []string{"nonce", "realm", "qop", "opaque"}
responseHeaders := strings.Split(resp.Header["Www-Authenticate"][0], ",")
for _, r := range responseHeaders {
for r := range strings.SplitSeq(resp.Header["Www-Authenticate"][0], ",") {
for _, w := range wantedHeaders {
if strings.Contains(r, w) {
result[w] = strings.Split(r, `"`)[1]
+6 -5
View File
@@ -27,6 +27,7 @@ import (
// ACME test suites.
type AcmeSuite struct {
BaseSuite
pebbleIP string
fakeDNSServer *dns.Server
}
@@ -63,11 +64,6 @@ const (
wildcardDomain = "*.acme.wtf"
)
func (s *AcmeSuite) getAcmeURL() string {
return fmt.Sprintf("https://%s/dir",
net.JoinHostPort(s.pebbleIP, "14000"))
}
func setupPebbleRootCA() (*http.Transport, error) {
path, err := filepath.Abs("fixtures/acme/ssl/pebble.minica.pem")
if err != nil {
@@ -540,3 +536,8 @@ func (s *AcmeSuite) retrieveAcmeCertificate(testCase acmeTestCase) {
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 {
BaseSuite
consulClient *api.Client
consulAgentClient *api.Client
consulURL string
@@ -53,47 +54,6 @@ func (s *ConsulCatalogSuite) 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() {
reg1 := &api.AgentServiceRegistration{
ID: "whoami1",
@@ -847,3 +807,44 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware() {
err = s.deregisterService("whoami1", false)
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.
type ConsulSuite struct {
BaseSuite
kvClient store.Store
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() {
// 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("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)
require.NoError(s.T(), err)
var version map[string]interface{}
var version map[string]any
assert.NoError(s.T(), json.Unmarshal(body, &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)
require.NoError(s.T(), err)
var version map[string]interface{}
var version map[string]any
assert.NoError(s.T(), json.Unmarshal(body, &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)
require.NoError(s.T(), err)
var version map[string]interface{}
var version map[string]any
assert.NoError(s.T(), json.Unmarshal(body, &version))
assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
+1
View File
@@ -14,6 +14,7 @@ import (
// ErrorPagesSuite test suites.
type ErrorPagesSuite struct {
BaseSuite
ErrorPageIP string
BackendIP string
}
+1
View File
@@ -24,6 +24,7 @@ import (
// etcd test suites.
type EtcdSuite struct {
BaseSuite
kvClient store.Store
etcdAddr string
}
+8 -2
View File
@@ -1273,6 +1273,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:
@@ -1663,8 +1664,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
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/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of
@@ -1907,6 +1909,7 @@ spec:
description: |-
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.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:
@@ -3703,6 +3706,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:
@@ -4093,8 +4097,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
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/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of
@@ -4337,6 +4342,7 @@ spec:
description: |-
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.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:
+4 -3
View File
@@ -19,6 +19,7 @@ import (
// HealthCheck test suites.
type HealthCheckSuite struct {
BaseSuite
whoami1IP string
whoami2IP string
whoami3IP string
@@ -305,7 +306,7 @@ func (s *HealthCheckSuite) TestPropagate() {
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
want4 := `IP: ` + s.whoami4IP
@@ -387,7 +388,7 @@ func (s *HealthCheckSuite) TestPropagate() {
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.
for range 2 {
@@ -413,7 +414,7 @@ func (s *HealthCheckSuite) TestPropagate() {
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.
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)
}
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)
if err := dec(in); err != nil {
return nil, err
@@ -199,13 +199,13 @@ func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(in
Server: srv,
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 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)
if err := stream.RecvMsg(m); err != nil {
return err
+34 -34
View File
@@ -876,40 +876,6 @@ func (s *HTTPSSuite) TestWithSNIDynamicConfigRouteWithTlsConfigurationDeletion()
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() {
file := s.adaptFile("fixtures/https/https_redirect.toml", struct{}{})
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() {
file := s.adaptFile("fixtures/https/max_concurrent_stream.toml", struct{}{})
+37 -36
View File
@@ -61,45 +61,12 @@ type composeDeploy struct {
type BaseSuite struct {
suite.Suite
containers map[string]testcontainers.Container
network *testcontainers.DockerNetwork
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() {
if isDockerDesktop(context.Background(), s.T()) {
_, err := os.Stat(tailscaleSecretFilePath)
@@ -400,7 +367,7 @@ func (s *BaseSuite) displayTraefikLog(output *bytes.Buffer) {
if output == nil || output.Len() == 0 {
log.WithoutContext().Info("No Traefik logs.")
} else {
for _, line := range strings.Split(output.String(), "\n") {
for line := range strings.SplitSeq(output.String(), "\n") {
log.WithoutContext().Info(line)
}
}
@@ -416,7 +383,7 @@ func (s *BaseSuite) getDockerHost() string {
return dockerHost
}
func (s *BaseSuite) adaptFile(path string, tempObjects interface{}) string {
func (s *BaseSuite) adaptFile(path string, tempObjects any) string {
// Load file
tmpl, err := template.ParseFiles(path)
require.NoError(s.T(), err)
@@ -504,3 +471,37 @@ func (s *BaseSuite) composeExec(service string, args ...string) string {
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
// +build !windows
package integration
+1
View File
@@ -14,6 +14,7 @@ import (
// Marathon test suites.
type MarathonSuite15 struct {
BaseSuite
marathonURL string
}
+1
View File
@@ -16,6 +16,7 @@ const containerNameMarathon = "marathon"
// Marathon test suites.
type MarathonSuite struct {
BaseSuite
marathonURL string
}
+6 -3
View File
@@ -3,6 +3,7 @@ package integration
import (
"bufio"
"net"
"strings"
"testing"
"time"
@@ -15,6 +16,7 @@ import (
type ProxyProtocolSuite struct {
BaseSuite
whoamiIP string
}
@@ -124,15 +126,16 @@ func proxyProtoRequest(address string, version byte) (string, error) {
}
// Read the response from the server
var content string
var content strings.Builder
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
content += scanner.Text() + "\n"
content.WriteString(scanner.Text())
content.WriteString("\n")
}
if scanner.Err() != nil {
return "", err
}
return content, nil
return content.String(), nil
}
+1
View File
@@ -12,6 +12,7 @@ import (
type RateLimitSuite struct {
BaseSuite
ServerIP string
}
+31 -30
View File
@@ -29,6 +29,7 @@ import (
// Redis test suites.
type RedisSentinelSuite struct {
BaseSuite
kvClient store.Store
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() {
file := s.adaptFile("fixtures/redis/sentinel.toml", struct{ RedisAddress string }{
RedisAddress: strings.Join(s.redisEndpoints, `","`),
@@ -202,3 +173,33 @@ func (s *RedisSentinelSuite) TestSentinelConfiguration() {
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.
type RedisSuite struct {
BaseSuite
kvClient store.Store
redisEndpoints []string
}
+1
View File
@@ -18,6 +18,7 @@ import (
type RestSuite struct {
BaseSuite
whoamiAddr string
}
+1
View File
@@ -15,6 +15,7 @@ import (
type RetrySuite struct {
BaseSuite
whoamiIP string
}
+19 -18
View File
@@ -12,6 +12,7 @@ import (
type TracingSuite struct {
BaseSuite
whoamiIP string
whoamiPort int
tracerZipkinIP string
@@ -43,15 +44,6 @@ func (s *TracingSuite) 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() {
s.startZipkin()
@@ -141,15 +133,6 @@ func (s *TracingSuite) TestZipkinAuth() {
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() {
s.startJaeger()
// 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"))
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
// Sleep pauses the current goroutine for at least the duration d.
//
// Deprecated: Use only when use another Try[...] functions is not possible.
func Sleep(d time.Duration) {
d = applyCIMultiplier(d)
@@ -92,10 +93,7 @@ func Do(timeout time.Duration, operation DoCondition) error {
panic("timeout must be larger than zero")
}
interval := time.Duration(math.Ceil(float64(timeout) / 15.0))
if interval > maxInterval {
interval = maxInterval
}
interval := min(time.Duration(math.Ceil(float64(timeout)/15.0)), maxInterval)
timeout = applyCIMultiplier(timeout)
@@ -166,7 +164,7 @@ func doRequest(action timedAction, timeout time.Duration, request *http.Request,
func applyCIMultiplier(timeout time.Duration) time.Duration {
ci := os.Getenv("CI")
if len(ci) > 0 {
log.Debug("Apply CI multiplier:", CITimeoutMultiplier)
log.WithoutContext().Debug("Apply CI multiplier:", CITimeoutMultiplier)
return time.Duration(float64(timeout) * CITimeoutMultiplier)
}
return timeout
+1
View File
@@ -25,6 +25,7 @@ import (
// Zk test suites.
type ZookeeperSuite struct {
BaseSuite
kvClient store.Store
zookeeperAddr string
}
+13 -13
View File
@@ -78,7 +78,7 @@ func main() {
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)
})
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{})
}
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)
element := &cmd.NewTraefikConfiguration().Configuration
@@ -309,7 +309,7 @@ type errWriter struct {
err error
}
func (ew *errWriter) writeln(a ...interface{}) {
func (ew *errWriter) writeln(a ...any) {
if ew.err != nil {
return
}
@@ -319,15 +319,15 @@ func (ew *errWriter) writeln(a ...interface{}) {
func genKVDynConfDoc(outputFile string) {
dynConfPath := "./docs/content/reference/dynamic-configuration/file.toml"
conf := map[string]interface{}{}
conf := map[string]any{}
_, err := toml.DecodeFile(dynConfPath, &conf)
if err != nil {
log.Fatal(err)
log.WithoutContext().Fatal(err)
}
file, err := os.Create(outputFile)
if err != nil {
log.Fatal(err)
log.WithoutContext().Fatal(err)
}
store := storeWriter{data: map[string]string{}}
@@ -335,7 +335,7 @@ func genKVDynConfDoc(outputFile string) {
c := client{store: store}
err = c.load("traefik", conf)
if err != nil {
log.Fatal(err)
log.WithoutContext().Fatal(err)
}
var keys []string
@@ -374,10 +374,10 @@ type client struct {
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 {
switch entry := v.(type) {
case map[string]interface{}:
case map[string]any:
key := path.Join(parentKey, k)
if len(entry) == 0 {
@@ -391,7 +391,7 @@ func (c client) load(parentKey string, conf map[string]interface{}) error {
return err
}
}
case []map[string]interface{}:
case []map[string]any:
for i, o := range entry {
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
}
}
case []interface{}:
case []any:
for i, o := range entry {
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 {
return err
}
@@ -411,7 +411,7 @@ func (c client) load(parentKey string, conf map[string]interface{}) error {
default:
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 {
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 {
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 {
r := reflect.ValueOf(rawValue).
Convert(reflect.TypeOf((map[string]interface{})(nil))).
Interface().(map[string]interface{})
Convert(reflect.TypeFor[map[string]any]()).
Interface().(map[string]any)
for k, v := range r {
switch tv := v.(type) {
case string:
labels[root+"."+k] = tv
case []interface{}:
case []any:
for i, e := range tv {
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)
}
endIndex := startIndex + perPage
if endIndex >= maximum {
endIndex = maximum
}
endIndex := min(startIndex+perPage, maximum)
nextPage := 1
if page*perPage < maximum {
+1 -1
View File
@@ -15,7 +15,7 @@ func init() {
expvar.Publish("Goroutines2", expvar.Func(goroutines))
}
func goroutines() interface{} {
func goroutines() any {
return runtime.NumGoroutine()
}
+3 -2
View File
@@ -30,6 +30,7 @@ func writeError(rw http.ResponseWriter, msg string, code int) {
type serviceInfoRepresentation struct {
*runtime.ServiceInfo
ServerStatus map[string]string `json:"serverStatus,omitempty"`
}
@@ -147,12 +148,12 @@ func getProviderName(id string) string {
return strings.SplitN(id, "@", 2)[1]
}
func extractType(element interface{}) string {
func extractType(element any) string {
v := reflect.ValueOf(element).Elem()
for i := range v.NumField() {
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 {
return keys[0].String()
}
+1
View File
@@ -15,6 +15,7 @@ import (
type entryPointRepresentation struct {
*static.EntryPoint
Name string `json:"name,omitempty"`
}
+1 -1
View File
@@ -235,7 +235,7 @@ func TestHandler_EntryPoints(t *testing.T) {
require.NoError(t, err)
if *updateExpected {
var results interface{}
var results any
err := json.Unmarshal(contents, &results)
require.NoError(t, err)
+3
View File
@@ -17,6 +17,7 @@ import (
type routerRepresentation struct {
*runtime.RouterInfo
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
}
@@ -35,6 +36,7 @@ func newRouterRepresentation(name string, rt *runtime.RouterInfo) routerRepresen
type serviceRepresentation struct {
*runtime.ServiceInfo
ServerStatus map[string]string `json:"serverStatus,omitempty"`
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
@@ -53,6 +55,7 @@ func newServiceRepresentation(name string, si *runtime.ServiceInfo) serviceRepre
type middlewareRepresentation struct {
*runtime.MiddlewareInfo
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"`
+1 -1
View File
@@ -950,7 +950,7 @@ func TestHandler_HTTP(t *testing.T) {
require.NoError(t, err)
if *updateExpected {
var results interface{}
var results any
err := json.Unmarshal(contents, &results)
require.NoError(t, err)
+1 -1
View File
@@ -232,7 +232,7 @@ func getProviders(conf static.Configuration) []string {
if !field.IsNil() {
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() {
providers = append(providers, "plugin-"+value.String())
}
+2 -2
View File
@@ -243,7 +243,7 @@ func TestHandler_Overview(t *testing.T) {
Rest: &rest.Provider{},
Rancher: &rancher.Provider{},
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)
if *updateExpected {
var results interface{}
var results any
err := json.Unmarshal(contents, &results)
require.NoError(t, err)
+3
View File
@@ -16,6 +16,7 @@ import (
type tcpRouterRepresentation struct {
*runtime.TCPRouterInfo
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
}
@@ -30,6 +31,7 @@ func newTCPRouterRepresentation(name string, rt *runtime.TCPRouterInfo) tcpRoute
type tcpServiceRepresentation struct {
*runtime.TCPServiceInfo
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"`
@@ -46,6 +48,7 @@ func newTCPServiceRepresentation(name string, si *runtime.TCPServiceInfo) tcpSer
type tcpMiddlewareRepresentation struct {
*runtime.TCPMiddlewareInfo
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"`
+1 -1
View File
@@ -821,7 +821,7 @@ func TestHandler_TCP(t *testing.T) {
require.NoError(t, err)
if *updateExpected {
var results interface{}
var results any
err := json.Unmarshal(contents, &results)
require.NoError(t, err)
+1 -1
View File
@@ -178,7 +178,7 @@ func TestHandler_GetMiddleware(t *testing.T) {
middlewareName string
conf runtime.Configuration
expectedStatus int
expected interface{}
expected any
}{
{
desc: "Middleware not found",
+2
View File
@@ -16,6 +16,7 @@ import (
type udpRouterRepresentation struct {
*runtime.UDPRouterInfo
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
}
@@ -30,6 +31,7 @@ func newUDPRouterRepresentation(name string, rt *runtime.UDPRouterInfo) udpRoute
type udpServiceRepresentation struct {
*runtime.UDPServiceInfo
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"`
+1 -1
View File
@@ -560,7 +560,7 @@ func TestHandler_UDP(t *testing.T) {
require.NoError(t, err)
if *updateExpected {
var results interface{}
var results any
err := json.Unmarshal(contents, &results)
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.
// 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{
BasePaths: []string{"/etc/traefik/traefik", "$XDG_CONFIG_HOME/traefik", "$HOME/.config/traefik", "./traefik"},
Extensions: []string{"toml", "yaml", "yml"},
+3 -3
View File
@@ -18,7 +18,7 @@ const (
)
// Hydrate hydrates a configuration.
func Hydrate(element interface{}) error {
func Hydrate(element any) error {
field := reflect.ValueOf(element)
return fill(field)
}
@@ -55,7 +55,7 @@ func fill(field reflect.Value) error {
setTyped(field, int32(defaultNumber))
case reflect.Int64:
switch field.Type() {
case reflect.TypeOf(types.Duration(time.Second)):
case reflect.TypeFor[types.Duration]():
setTyped(field, types.Duration(defaultNumber*time.Second))
default:
setTyped(field, int64(defaultNumber))
@@ -81,7 +81,7 @@ func fill(field reflect.Value) error {
return nil
}
func setTyped(field reflect.Value, i interface{}) {
func setTyped(field reflect.Value, i any) {
baseValue := reflect.ValueOf(i)
if field.Kind().String() == field.Type().String() {
field.Set(baseValue)
+2 -2
View File
@@ -21,7 +21,7 @@ func TestDeepCopy(t *testing.T) {
cfgDeepCopy := cfg.DeepCopy()
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)
// Update cfg
@@ -32,6 +32,6 @@ func TestDeepCopy(t *testing.T) {
assert.Equal(t, cfgCopy, 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)
}
+1
View File
@@ -389,6 +389,7 @@ func (s *IPStrategy) Get() (ip.Strategy, error) {
// IPWhiteList holds the IP whitelist middleware configuration.
// This middleware limits allowed requests based on the client IP.
// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
//
// Deprecated: please use IPAllowList instead.
type IPWhiteList struct {
// 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) {
m := map[string]interface{}{
m := map[string]any{
"name": "bar",
}
p := PluginConf{
"config": map[string]interface{}{
"config": map[string]any{
"foo": m,
},
}
@@ -64,7 +64,7 @@ func TestPluginConf_DeepCopy_map(t *testing.T) {
func TestPluginConf_DeepCopy_panic(t *testing.T) {
p := &PluginConf{
"config": map[string]interface{}{
"config": map[string]any{
"foo": &Foo{Name: "gigi"},
},
}
+1
View File
@@ -26,6 +26,7 @@ type TCPInFlightConn struct {
// TCPIPWhiteList holds the TCP IPWhiteList middleware configuration.
// This middleware limits allowed requests based on the client IP.
// More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
//
// Deprecated: please use IPAllowList instead.
type TCPIPWhiteList struct {
// 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
// untyped nodes -> nodes augmented with metadata such as kind (inferred from 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 {
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})
}
func getRootFieldNames(rootName string, element interface{}) []string {
func getRootFieldNames(rootName string, element any) []string {
if element == 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.
// 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...)
}
+8 -14
View File
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"maps"
"slices"
"sort"
"sync"
@@ -72,6 +73,7 @@ func unique(src []string) []string {
// RouterInfo holds information about a currently running HTTP router.
type RouterInfo struct {
*dynamic.Router // dynamic configuration
// Err contains all the errors that occurred during router's creation.
Err []string `json:"error,omitempty"`
// Status reports whether the router is disabled, in a warning state, or all good (enabled).
@@ -84,11 +86,9 @@ type RouterInfo struct {
// AddError adds err to r.Err, if it does not already exist.
// If critical is set, r is marked as disabled.
func (r *RouterInfo) AddError(err error, critical bool) {
for _, value := range r.Err {
if value == err.Error() {
if slices.Contains(r.Err, err.Error()) {
return
}
}
r.Err = append(r.Err, err.Error())
if critical {
@@ -105,6 +105,7 @@ func (r *RouterInfo) AddError(err error, critical bool) {
// MiddlewareInfo holds information about a currently running middleware.
type MiddlewareInfo struct {
*dynamic.Middleware // dynamic configuration
// Err contains all the errors that occurred during service creation.
Err []string `json:"error,omitempty"`
Status string `json:"status,omitempty"`
@@ -114,11 +115,9 @@ type MiddlewareInfo struct {
// AddError adds err to s.Err, if it does not already exist.
// If critical is set, m is marked as disabled.
func (m *MiddlewareInfo) AddError(err error, critical bool) {
for _, value := range m.Err {
if value == err.Error() {
if slices.Contains(m.Err, err.Error()) {
return
}
}
m.Err = append(m.Err, err.Error())
if critical {
@@ -135,6 +134,7 @@ func (m *MiddlewareInfo) AddError(err error, critical bool) {
// ServiceInfo holds information about a currently running service.
type ServiceInfo struct {
*dynamic.Service // dynamic configuration
// Err contains all the errors that occurred during service creation.
Err []string `json:"error,omitempty"`
// Status reports whether the service is disabled, in a warning state, or all good (enabled).
@@ -150,11 +150,9 @@ type ServiceInfo struct {
// AddError adds err to s.Err, if it does not already exist.
// If critical is set, s is marked as disabled.
func (s *ServiceInfo) AddError(err error, critical bool) {
for _, value := range s.Err {
if value == err.Error() {
if slices.Contains(s.Err, err.Error()) {
return
}
}
s.Err = append(s.Err, err.Error())
if critical {
@@ -190,9 +188,5 @@ func (s *ServiceInfo) GetAllStatus() map[string]string {
return nil
}
allStatus := make(map[string]string, len(s.serverStatus))
for k, v := range s.serverStatus {
allStatus[k] = v
}
return allStatus
return maps.Clone(s.serverStatus)
}
+6 -9
View File
@@ -48,6 +48,7 @@ func (c *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoi
// TCPRouterInfo holds information about a currently running TCP router.
type TCPRouterInfo struct {
*dynamic.TCPRouter // dynamic configuration
Err []string `json:"error,omitempty"` // initialization error
// 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.
@@ -59,11 +60,9 @@ type TCPRouterInfo struct {
// AddError adds err to r.Err, if it does not already exist.
// If critical is set, r is marked as disabled.
func (r *TCPRouterInfo) AddError(err error, critical bool) {
for _, value := range r.Err {
if value == err.Error() {
if slices.Contains(r.Err, err.Error()) {
return
}
}
r.Err = append(r.Err, err.Error())
if critical {
@@ -80,6 +79,7 @@ func (r *TCPRouterInfo) AddError(err error, critical bool) {
// TCPServiceInfo holds information about a currently running TCP service.
type TCPServiceInfo struct {
*dynamic.TCPService // dynamic configuration
Err []string `json:"error,omitempty"` // initialization error
// 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.
@@ -91,11 +91,9 @@ type TCPServiceInfo struct {
// AddError adds err to s.Err, if it does not already exist.
// If critical is set, s is marked as disabled.
func (s *TCPServiceInfo) AddError(err error, critical bool) {
for _, value := range s.Err {
if value == err.Error() {
if slices.Contains(s.Err, err.Error()) {
return
}
}
s.Err = append(s.Err, err.Error())
if critical {
@@ -112,6 +110,7 @@ func (s *TCPServiceInfo) AddError(err error, critical bool) {
// TCPMiddlewareInfo holds information about a currently running middleware.
type TCPMiddlewareInfo struct {
*dynamic.TCPMiddleware // dynamic configuration
// Err contains all the errors that occurred during service creation.
Err []string `json:"error,omitempty"`
Status string `json:"status,omitempty"`
@@ -121,11 +120,9 @@ type TCPMiddlewareInfo struct {
// AddError adds err to s.Err, if it does not already exist.
// If critical is set, m is marked as disabled.
func (m *TCPMiddlewareInfo) AddError(err error, critical bool) {
for _, value := range m.Err {
if value == err.Error() {
if slices.Contains(m.Err, err.Error()) {
return
}
}
m.Err = append(m.Err, err.Error())
if critical {
+4 -6
View File
@@ -54,6 +54,7 @@ func (c *Configuration) GetUDPRoutersByEntryPoints(ctx context.Context, entryPoi
// UDPRouterInfo holds information about a currently running UDP router.
type UDPRouterInfo struct {
*dynamic.UDPRouter // dynamic configuration
Err []string `json:"error,omitempty"` // initialization error
// 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.
@@ -65,11 +66,9 @@ type UDPRouterInfo struct {
// AddError adds err to r.Err, if it does not already exist.
// If critical is set, r is marked as disabled.
func (r *UDPRouterInfo) AddError(err error, critical bool) {
for _, value := range r.Err {
if value == err.Error() {
if slices.Contains(r.Err, err.Error()) {
return
}
}
r.Err = append(r.Err, err.Error())
if critical {
@@ -86,6 +85,7 @@ func (r *UDPRouterInfo) AddError(err error, critical bool) {
// UDPServiceInfo holds information about a currently running UDP service.
type UDPServiceInfo struct {
*dynamic.UDPService // dynamic configuration
Err []string `json:"error,omitempty"` // initialization error
// 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.
@@ -97,11 +97,9 @@ type UDPServiceInfo struct {
// AddError adds err to s.Err, if it does not already exist.
// If critical is set, s is marked as disabled.
func (s *UDPServiceInfo) AddError(err error, critical bool) {
for _, value := range s.Err {
if value == err.Error() {
if slices.Contains(s.Err, err.Error()) {
return
}
}
s.Err = append(s.Err, err.Error())
if critical {
+1 -1
View File
@@ -1,4 +1,4 @@
package static
// 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()
}
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.
func (c *Configuration) ValidateConfiguration() error {
var acmeEmail string
@@ -342,6 +328,20 @@ func (c *Configuration) ValidateConfiguration() error {
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 {
if len(caServerSrc) == 0 {
return DefaultAcmeCAServer
+19 -17
View File
@@ -82,10 +82,19 @@ type backendURL struct {
// BackendConfig HealthCheck configuration for a backend.
type BackendConfig struct {
Options
name string
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) {
u, err := serverURL.Parse(b.Path)
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
// a non-nil error with a meaningful description why the health check failed.
func checkHealth(serverURL *url.URL, backend *BackendConfig) error {
@@ -286,6 +287,16 @@ type StatusUpdater interface {
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.
func NewLBStatusUpdater(bh BalancerHandler, info *runtime.ServiceInfo, hc *dynamic.ServerHealthCheck) *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
// status of the Balancer changes.
// 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
// and the test assertions reference the counters.
*sync.RWMutex
numRemovedServers int
numUpsertedServers int
servers []*url.URL
+1
View File
@@ -17,6 +17,7 @@ const (
// If operation() takes more than MinJobInterval, Reset() is called in NextBackOff().
type BackOff struct {
*backoff.ExponentialBackOff
MinJobInterval time.Duration
}
+24 -13
View File
@@ -9,68 +9,79 @@ import (
)
// Debug logs a message at level Debug on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Debug(...) instead.
func Debug(args ...interface{}) {
func Debug(args ...any) {
mainLogger.Debug(args...)
}
// Debugf logs a message at level Debug on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Debugf(...) instead.
func Debugf(format string, args ...interface{}) {
func Debugf(format string, args ...any) {
mainLogger.Debugf(format, args...)
}
// Info logs a message at level Info on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Info(...) instead.
func Info(args ...interface{}) {
func Info(args ...any) {
mainLogger.Info(args...)
}
// Infof logs a message at level Info on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Infof(...) instead.
func Infof(format string, args ...interface{}) {
func Infof(format string, args ...any) {
mainLogger.Infof(format, args...)
}
// Warn logs a message at level Warn on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Warn(...) instead.
func Warn(args ...interface{}) {
func Warn(args ...any) {
mainLogger.Warn(args...)
}
// Warnf logs a message at level Warn on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Warnf(...) instead.
func Warnf(format string, args ...interface{}) {
func Warnf(format string, args ...any) {
mainLogger.Warnf(format, args...)
}
// Error logs a message at level Error on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Error(...) instead.
func Error(args ...interface{}) {
func Error(args ...any) {
mainLogger.Error(args...)
}
// Errorf logs a message at level Error on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Errorf(...) instead.
func Errorf(format string, args ...interface{}) {
func Errorf(format string, args ...any) {
mainLogger.Errorf(format, args...)
}
// Panic logs a message at level Panic on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Panic(...) instead.
func Panic(args ...interface{}) {
func Panic(args ...any) {
mainLogger.Panic(args...)
}
// Fatal logs a message at level Fatal on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Fatal(...) instead.
func Fatal(args ...interface{}) {
func Fatal(args ...any) {
mainLogger.Fatal(args...)
}
// Fatalf logs a message at level Fatal on the standard logger.
//
// Deprecated: use log.FromContext(ctx).Fatalf(...) instead.
func Fatalf(format string, args ...interface{}) {
func Fatalf(format string, args ...any) {
mainLogger.Fatalf(format, args...)
}
@@ -84,7 +95,7 @@ func AddHook(hook logrus.Hook) {
func CustomWriterLevel(level logrus.Level, maxScanTokenSize int) *io.PipeWriter {
reader, writer := io.Pipe()
var printFunc func(args ...interface{})
var printFunc func(args ...any)
switch level {
case logrus.DebugLevel:
@@ -111,7 +122,7 @@ func CustomWriterLevel(level logrus.Level, maxScanTokenSize int) *io.PipeWriter
// extract from github.com/Sirupsen/logrus/writer.go
// 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)
if scanTokenSize > bufio.MaxScanTokenSize {
+1 -1
View File
@@ -58,7 +58,7 @@ func RegisterDatadog(ctx context.Context, config *types.Datadog) Registry {
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...)
return nil
}))
+5 -5
View File
@@ -36,16 +36,16 @@ func (c MultiCounterWithHeaders) With(headers http.Header, labelValues ...string
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.
type CounterWithNoopHeaders struct {
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.
func (c CounterWithNoopHeaders) Add(delta float64) {
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,
RetentionPolicy: config.RetentionPolicy,
},
kitlog.LoggerFunc(func(keyvals ...interface{}) error {
kitlog.LoggerFunc(func(keyvals ...any) error {
log.WithoutContext().WithField(log.MetricsProviderName, "influxdb").Info(keyvals...)
return nil
}))
+1 -1
View File
@@ -37,7 +37,7 @@ func RegisterInfluxDB2(ctx context.Context, config *types.InfluxDB2) Registry {
influxDB2Store = influx.New(
config.AdditionalLabels,
influxdb.BatchPointsConfig{},
kitlog.LoggerFunc(func(kv ...interface{}) error {
kitlog.LoggerFunc(func(kv ...any) error {
log.FromContext(ctx).Error(kv...)
return nil
}),
+1 -1
View File
@@ -55,7 +55,7 @@ func RegisterStatsd(ctx context.Context, config *types.Statsd) Registry {
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...)
return nil
}))
+1 -1
View File
@@ -121,7 +121,7 @@ func init() {
}
// 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.
type LogData struct {
@@ -52,7 +52,7 @@ func (f *CommonLogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
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 == nil {
return defaultValue
@@ -14,12 +14,12 @@ func TestCommonLogFormatter_Format(t *testing.T) {
testCases := []struct {
name string
data map[string]interface{}
data map[string]any
expectedLog string
}{
{
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),
Duration: 123 * time.Second,
ClientHost: "10.0.0.1",
@@ -40,7 +40,7 @@ func TestCommonLogFormatter_Format(t *testing.T) {
},
{
name: "all data",
data: map[string]interface{}{
data: map[string]any{
StartUTC: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC),
Duration: 123 * time.Second,
ClientHost: "10.0.0.1",
@@ -61,7 +61,7 @@ func TestCommonLogFormatter_Format(t *testing.T) {
},
{
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),
Duration: 123 * time.Second,
ClientHost: "10.0.0.1",
@@ -106,7 +106,7 @@ func Test_toLog(t *testing.T) {
fieldName string
defaultValue string
quoted bool
expectedLog interface{}
expectedLog any
}{
{
desc: "Should return int 1",
+20 -20
View File
@@ -116,7 +116,7 @@ func lineCount(t *testing.T, fileName string) int {
}
count := 0
for _, line := range strings.Split(string(fileContents), "\n") {
for line := range strings.SplitSeq(string(fileContents), "\n") {
if strings.TrimSpace(line) == "" {
continue
}
@@ -259,32 +259,32 @@ func TestLoggerCLFWithBufferingSize(t *testing.T) {
assertValidLogData(t, expectedLog, logData)
}
func assertString(exp string) func(t *testing.T, actual interface{}) {
return func(t *testing.T, actual interface{}) {
func assertString(exp string) func(t *testing.T, actual any) {
return func(t *testing.T, actual any) {
t.Helper()
assert.Equal(t, exp, actual)
}
}
func assertNotEmpty() func(t *testing.T, actual interface{}) {
return func(t *testing.T, actual interface{}) {
func assertNotEmpty() func(t *testing.T, actual any) {
return func(t *testing.T, actual any) {
t.Helper()
assert.NotEmpty(t, actual)
}
}
func assertFloat64(exp float64) func(t *testing.T, actual interface{}) {
return func(t *testing.T, actual interface{}) {
func assertFloat64(exp float64) func(t *testing.T, actual any) {
return func(t *testing.T, actual any) {
t.Helper()
assert.InDelta(t, exp, actual, delta)
}
}
func assertFloat64NotZero() func(t *testing.T, actual interface{}) {
return func(t *testing.T, actual interface{}) {
func assertFloat64NotZero() func(t *testing.T, actual any) {
return func(t *testing.T, actual any) {
t.Helper()
assert.NotZero(t, actual)
@@ -296,7 +296,7 @@ func TestLoggerJSON(t *testing.T) {
desc string
config *types.AccessLog
tls bool
expected map[string]func(t *testing.T, value interface{})
expected map[string]func(t *testing.T, value any)
}{
{
desc: "default config",
@@ -304,7 +304,7 @@ func TestLoggerJSON(t *testing.T) {
FilePath: "",
Format: JSONFormat,
},
expected: map[string]func(t *testing.T, value interface{}){
expected: map[string]func(t *testing.T, value any){
RequestContentSize: assertFloat64(0),
RequestHost: assertString(testHostname),
RequestAddr: assertString(testHostname),
@@ -344,7 +344,7 @@ func TestLoggerJSON(t *testing.T) {
Format: JSONFormat,
},
tls: true,
expected: map[string]func(t *testing.T, value interface{}){
expected: map[string]func(t *testing.T, value any){
RequestContentSize: assertFloat64(0),
RequestHost: assertString(testHostname),
RequestAddr: assertString(testHostname),
@@ -388,7 +388,7 @@ func TestLoggerJSON(t *testing.T) {
DefaultMode: "drop",
},
},
expected: map[string]func(t *testing.T, value interface{}){
expected: map[string]func(t *testing.T, value any){
"level": assertString("info"),
"msg": assertString(""),
"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"),
"msg": assertString(""),
"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"),
"msg": assertString(""),
"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),
"level": assertString("info"),
"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),
"level": assertString("info"),
"msg": assertString(""),
@@ -506,7 +506,7 @@ func TestLoggerJSON(t *testing.T) {
logData, err := os.ReadFile(logFilePath)
require.NoError(t, err)
jsonData := make(map[string]interface{})
jsonData := make(map[string]any)
err = json.Unmarshal(logData, &jsonData)
require.NoError(t, err)
@@ -520,7 +520,7 @@ func TestLoggerJSON(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),
RequestHost: assertString(testHostname),
RequestAddr: assertString(testHostname),
@@ -563,7 +563,7 @@ func TestLogger_AbortedRequest(t *testing.T) {
logData, err := os.ReadFile(config.FilePath)
require.NoError(t, err)
jsonData := make(map[string]interface{})
jsonData := make(map[string]any)
err = json.Unmarshal(logData, &jsonData)
require.NoError(t, err)
+1 -1
View File
@@ -22,7 +22,7 @@ func RemoveConnectionHeaders(req *http.Request) {
}
for _, f := range req.Header[connectionHeader] {
for _, sf := range strings.Split(f, ",") {
for sf := range strings.SplitSeq(f, ",") {
if sf = textproto.TrimString(sf); 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 {
return c.rw.Size()
}
@@ -115,6 +101,20 @@ func (c *Capture) RequestSize() int64 {
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 {
// source ReadCloser from where the request body is read.
source io.ReadCloser
+17 -22
View File
@@ -4,6 +4,7 @@ import (
"bufio"
"context"
"fmt"
"maps"
"net"
"net/http"
"net/url"
@@ -169,16 +170,6 @@ func (cc *codeCatcher) Header() http.Header {
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) {
// If WriteHeader was already called from the caller, this is a NOOP.
// Otherwise, cc.code is actually a 200 here.
@@ -204,9 +195,7 @@ func (cc *codeCatcher) WriteHeader(code int) {
if code >= 100 && code <= 199 {
// Multiple informational status codes can be used,
// so here the copy is not appending the values to not repeat them.
for k, v := range cc.Header() {
cc.responseWriter.Header()[k] = v
}
maps.Copy(cc.responseWriter.Header(), cc.Header())
cc.responseWriter.WriteHeader(code)
return
@@ -224,9 +213,8 @@ func (cc *codeCatcher) WriteHeader(code int) {
// The copy is not appending the values,
// to not repeat them in case any informational status code has been written.
for k, v := range cc.Header() {
cc.responseWriter.Header()[k] = v
}
maps.Copy(cc.responseWriter.Header(), cc.Header())
cc.responseWriter.WriteHeader(cc.code)
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 {
*codeCatcher
}
@@ -332,17 +330,14 @@ func (r *codeModifierWithoutCloseNotify) WriteHeader(code int) {
if code >= 100 && code <= 199 {
// Multiple informational status codes can be used,
// so here the copy is not appending the values to not repeat them.
for k, v := range r.headerMap {
r.responseWriter.Header()[k] = v
}
maps.Copy(r.responseWriter.Header(), r.headerMap)
r.responseWriter.WriteHeader(code)
return
}
for k, v := range r.headerMap {
r.responseWriter.Header()[k] = v
}
maps.Copy(r.responseWriter.Header(), r.headerMap)
r.responseWriter.WriteHeader(r.code)
r.headerSent = true
}
@@ -81,13 +81,6 @@ func NewXForwarded(insecure bool, trustedIPs []string, connectionHeaders []strin
}, 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,
// like "[fe80::d806:a55d:eb1b:49cc%vEthernet (vmxnet3 Ethernet Adapter - Virtual Switch)]:64692".
func removeIPv6Zone(clientIP string) string {
@@ -138,6 +131,28 @@ func forwardedPort(req *http.Request) string {
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) {
if clientIP, _, err := net.SplitHostPort(outreq.RemoteAddr); err == nil {
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) {
var reqUpType string
if httpguts.HeaderValuesContainsToken(req.Header[connection], upgrade) {
@@ -209,7 +209,7 @@ func (x *XForwarded) removeConnectionHeaders(req *http.Request) {
var connectionHopByHopHeaders []string
for _, f := range req.Header[connection] {
for _, sf := range strings.Split(f, ",") {
for sf := range strings.SplitSeq(f, ",") {
if sf = textproto.TrimString(sf); sf != "" {
// Connection header cannot dictate to remove X- headers managed by Traefik,
// 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.
// This method is called AFTER the response is generated from the backend
// and can merge/override headers from the backend response.
@@ -138,6 +117,27 @@ func (s *Header) PostRequestModifyResponseHeaders(res *http.Response) error {
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,
// and returns if it is a preflight request.
// 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 {
expected
desc string
host string
cfg dynamic.Headers
expected
}{
{
desc: "http should return a 301",
+5 -4
View File
@@ -27,6 +27,7 @@ func newResponseRecorder(rw http.ResponseWriter) recorder {
// later analysis.
type responseRecorder struct {
http.ResponseWriter
statusCode int
}
@@ -40,10 +41,6 @@ func (r *responseRecorderWithCloseNotify) CloseNotify() <-chan bool {
return r.ResponseWriter.(http.CloseNotifier).CloseNotify()
}
func (r *responseRecorder) getCode() int {
return r.statusCode
}
// WriteHeader captures the status code for later retrieval.
func (r *responseRecorder) WriteHeader(status int) {
r.ResponseWriter.WriteHeader(status)
@@ -61,3 +58,7 @@ func (r *responseRecorder) 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
}
burst := config.Burst
if burst < 1 {
burst = 1
}
burst := max(config.Burst, 1)
period := time.Duration(config.Period)
if period < 0 {
@@ -283,11 +283,8 @@ func TestRateLimit(t *testing.T) {
stop := time.Now()
elapsed := stop.Sub(start)
burst := test.config.Burst
if burst < 1 {
// actual default value
burst = 1
}
// actual default value if burst < 1
burst := max(test.config.Burst, 1)
period := time.Duration(test.config.Period)
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/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.
return panicValue != nil && panicValue != http.ErrAbortHandler
}
+2 -4
View File
@@ -5,6 +5,7 @@ import (
"context"
"fmt"
"io"
"maps"
"math"
"net"
"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.
// So it is now safe to alter current response headers with headers collected during
// the latest try before writing headers to client.
headers := r.responseWriter.Header()
for header, value := range r.headers {
headers[header] = value
}
maps.Copy(r.responseWriter.Header(), r.headers)
r.responseWriter.WriteHeader(code)
+1
View File
@@ -29,6 +29,7 @@ func NewEntryPoint(ctx context.Context, t *tracing.Tracing, entryPointName strin
type entryPointMiddleware struct {
*tracing.Tracing
entryPoint string
next http.Handler
}
+5 -5
View File
@@ -13,7 +13,7 @@ import (
func TestEntryPointMiddleware(t *testing.T) {
type expected struct {
Tags map[string]interface{}
Tags map[string]any
OperationName string
}
@@ -29,10 +29,10 @@ func TestEntryPointMiddleware(t *testing.T) {
entryPoint: "test",
spanNameLimit: 0,
tracing: &trackingBackenMock{
tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}},
tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]any)}},
},
expected: expected{
Tags: map[string]interface{}{
Tags: map[string]any{
"span.kind": ext.SpanKindRPCServerEnum,
"http.method": http.MethodGet,
"component": "",
@@ -47,10 +47,10 @@ func TestEntryPointMiddleware(t *testing.T) {
entryPoint: "test",
spanNameLimit: 25,
tracing: &trackingBackenMock{
tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}},
tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]any)}},
},
expected: expected{
Tags: map[string]interface{}{
Tags: map[string]any{
"span.kind": ext.SpanKindRPCServerEnum,
"http.method": http.MethodGet,
"component": "",
+9 -9
View File
@@ -13,7 +13,7 @@ import (
func TestNewForwarder(t *testing.T) {
type expected struct {
Tags map[string]interface{}
Tags map[string]any
OperationName string
}
@@ -29,12 +29,12 @@ func TestNewForwarder(t *testing.T) {
desc: "Simple Forward Tracer without truncation and hashing",
spanNameLimit: 101,
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",
router: "some-service.domain.tld",
expected: expected{
Tags: map[string]interface{}{
Tags: map[string]any{
"http.host": "www.test.com",
"http.method": "GET",
"http.url": "http://www.test.com/toto",
@@ -49,12 +49,12 @@ func TestNewForwarder(t *testing.T) {
desc: "Simple Forward Tracer with truncation and hashing",
spanNameLimit: 101,
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",
router: "some-service-100.slug.namespace.environment.domain.tld",
expected: expected{
Tags: map[string]interface{}{
Tags: map[string]any{
"http.host": "www.test.com",
"http.method": "GET",
"http.url": "http://www.test.com/toto",
@@ -69,12 +69,12 @@ func TestNewForwarder(t *testing.T) {
desc: "Exactly 101 chars",
spanNameLimit: 101,
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",
router: "some-service1.namespace.environment.domain.tld",
expected: expected{
Tags: map[string]interface{}{
Tags: map[string]any{
"http.host": "www.test.com",
"http.method": "GET",
"http.url": "http://www.test.com/toto",
@@ -89,12 +89,12 @@ func TestNewForwarder(t *testing.T) {
desc: "More than 101 chars",
spanNameLimit: 101,
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",
router: "some-service1.backend.namespace.environment.domain.tld",
expected: expected{
Tags: map[string]interface{}{
Tags: map[string]any{
"http.host": "www.test.com",
"http.method": "GET",
"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.
func (n MockTracer) Inject(sp opentracing.SpanContext, format, carrier interface{}) error {
func (n MockTracer) Inject(sp opentracing.SpanContext, format, carrier any) error {
return nil
}
// 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
}
@@ -35,29 +35,29 @@ func (n MockSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {}
// MockSpan a span mock.
type MockSpan struct {
OpName string
Tags map[string]interface{}
Tags map[string]any
}
func (n *MockSpan) Context() opentracing.SpanContext { return MockSpanContext{} }
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) SetTag(key string, value interface{}) opentracing.Span {
func (n *MockSpan) SetTag(key string, value any) opentracing.Span {
n.Tags[key] = value
return n
}
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) FinishWithOptions(opts opentracing.FinishOptions) {}
func (n *MockSpan) SetOperationName(operationName string) opentracing.Span { return n }
func (n *MockSpan) Tracer() opentracing.Tracer { return MockTracer{} }
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) Reset() {
n.Tags = make(map[string]interface{})
n.Tags = make(map[string]any)
}
type trackingBackenMock struct {
+1
View File
@@ -22,6 +22,7 @@ func newStatusCodeRecoder(rw http.ResponseWriter, status int) statusCodeRecoder
type statusCodeWithoutCloseNotify struct {
http.ResponseWriter
status int
}
+1
View File
@@ -32,6 +32,7 @@ var httpFuncs = map[string]func(*mux.Route, ...string) error{
// Muxer handles routing with rules.
type Muxer struct {
*mux.Router
parser predicate.Parser
}
+29 -29
View File
@@ -245,35 +245,6 @@ func (c *Client) Unzip(pName, pVersion string) error {
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 {
rc, err := f.Open()
if err != nil {
@@ -404,6 +375,35 @@ func (c *Client) ResetAll() error {
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 {
return filepath.Join(c.archives, filepath.FromSlash(pName), pVersion+".zip")
}
+3 -3
View File
@@ -13,7 +13,7 @@ import (
)
// 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 {
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
}
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)
if len(results) != 1 {
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
}
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)
if err != nil {
return nil, err
+3 -3
View File
@@ -24,7 +24,7 @@ type PP interface {
}
type _PP struct {
IValue interface{}
IValue any
WInit func() error
WProvide func(cfgChan chan<- json.Marshaler) error
WStop func() error
@@ -52,7 +52,7 @@ func ppSymbols() map[string]map[string]reflect.Value {
}
// 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 {
return nil, fmt.Errorf("no plugin definition in the static configuration: %s", pName)
}
@@ -81,7 +81,7 @@ type Provider struct {
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
if basePkg == "" {
basePkg = strings.ReplaceAll(path.Base(builder.Import), "-", "_")
+1 -1
View File
@@ -23,5 +23,5 @@ type Manifest struct {
BasePkg string `yaml:"basePkg"`
Compatibility string `yaml:"compatibility"`
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"
"encoding/json"
"io"
"maps"
"os"
"sync"
@@ -29,6 +30,52 @@ func NewLocalStore(filename string, routinesPool *safe.Pool) *LocalStore {
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) {
s.lock.Lock()
defer s.lock.Unlock()
@@ -121,8 +168,7 @@ func (s *LocalStore) listenSaveAction(routinesPool *safe.Pool) {
logger.Error(err)
}
err = os.WriteFile(s.filename, data, 0o600)
if err != nil {
if err := os.WriteFile(s.filename, data, 0o600); err != nil {
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`.
func (s *LocalStore) unSafeCopyOfStoredData() map[string]*StoredData {
result := map[string]*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
return maps.Clone(s.storedData)
}

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