mirror of
https://github.com/traefik/traefik
synced 2026-02-03 08:50:32 +00:00
Merge current v3.6 into master
This commit is contained in:
+2
-11
@@ -84,13 +84,7 @@ func (c *searchCriterion) filterMiddleware(mns []string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, mn := range mns {
|
||||
if c.MiddlewareName == mn {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return slices.Contains(mns, c.MiddlewareName)
|
||||
}
|
||||
|
||||
func pagination(request *http.Request, maximum int) (pageInfo, error) {
|
||||
@@ -109,10 +103,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
@@ -15,7 +15,7 @@ func init() {
|
||||
expvar.Publish("Goroutines2", expvar.Func(goroutines))
|
||||
}
|
||||
|
||||
func goroutines() interface{} {
|
||||
func goroutines() any {
|
||||
return runtime.NumGoroutine()
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -30,11 +30,13 @@ func writeError(rw http.ResponseWriter, msg string, code int) {
|
||||
|
||||
type serviceInfoRepresentation struct {
|
||||
*runtime.ServiceInfo
|
||||
|
||||
ServerStatus map[string]string `json:"serverStatus,omitempty"`
|
||||
}
|
||||
|
||||
type tcpServiceInfoRepresentation struct {
|
||||
*runtime.TCPServiceInfo
|
||||
|
||||
ServerStatus map[string]string `json:"serverStatus,omitempty"`
|
||||
}
|
||||
|
||||
@@ -164,7 +166,7 @@ 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)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
type entryPointRepresentation struct {
|
||||
*static.EntryPoint
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
|
||||
type routerRepresentation struct {
|
||||
*runtime.RouterInfo
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
}
|
||||
@@ -34,6 +35,7 @@ func newRouterRepresentation(name string, rt *runtime.RouterInfo) routerRepresen
|
||||
|
||||
type serviceRepresentation struct {
|
||||
*runtime.ServiceInfo
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
@@ -52,6 +54,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"`
|
||||
|
||||
@@ -1028,7 +1028,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)
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ func TestHandler_Overview(t *testing.T) {
|
||||
KubernetesCRD: &crd.Provider{},
|
||||
Rest: &rest.Provider{},
|
||||
Plugin: map[string]static.PluginConf{
|
||||
"test": map[string]interface{}{},
|
||||
"test": map[string]any{},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -292,7 +292,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)
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
type tcpRouterRepresentation struct {
|
||||
*runtime.TCPRouterInfo
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
}
|
||||
@@ -29,6 +30,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"`
|
||||
@@ -47,6 +49,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"`
|
||||
|
||||
@@ -964,7 +964,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)
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
type udpRouterRepresentation struct {
|
||||
*runtime.UDPRouterInfo
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
}
|
||||
@@ -29,6 +30,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"`
|
||||
|
||||
@@ -594,7 +594,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)
|
||||
|
||||
|
||||
+34
-33
@@ -82,7 +82,7 @@ func logDeprecations(arguments []string) (bool, error) {
|
||||
if filePath != "" {
|
||||
// We don't rely on the Parser file loader here to avoid issues with unknown fields.
|
||||
// Parse file content into a generic map.
|
||||
var fileConfig map[string]interface{}
|
||||
var fileConfig map[string]any
|
||||
if err := file.Decode(filePath, &fileConfig); err != nil {
|
||||
return false, fmt.Errorf("decoding configuration file %s: %w", filePath, err)
|
||||
}
|
||||
@@ -106,7 +106,7 @@ func logDeprecations(arguments []string) (bool, error) {
|
||||
if len(vars) > 0 {
|
||||
// We don't rely on the Parser env loader here to avoid issues with unknown fields.
|
||||
// Decode environment variables to a generic map.
|
||||
var envConfig map[string]interface{}
|
||||
var envConfig map[string]any
|
||||
if err := env.Decode(vars, env.DefaultNamePrefix, &envConfig); err != nil {
|
||||
return false, fmt.Errorf("decoding environment variables: %w", err)
|
||||
}
|
||||
@@ -130,9 +130,9 @@ func logDeprecations(arguments []string) (bool, error) {
|
||||
|
||||
// flattenToLabels recursively flattens a nested map into label key-value pairs.
|
||||
// Example: {"experimental": {"http3": true}} -> {"traefik.experimental.http3": "true"}.
|
||||
func flattenToLabels(config interface{}, currKey string, labels map[string]string) {
|
||||
func flattenToLabels(config any, currKey string, labels map[string]string) {
|
||||
switch v := config.(type) {
|
||||
case map[string]interface{}:
|
||||
case map[string]any:
|
||||
for key, value := range v {
|
||||
newKey := key
|
||||
if currKey != "" {
|
||||
@@ -140,7 +140,7 @@ func flattenToLabels(config interface{}, currKey string, labels map[string]strin
|
||||
}
|
||||
flattenToLabels(value, newKey, labels)
|
||||
}
|
||||
case []interface{}:
|
||||
case []any:
|
||||
for i, item := range v {
|
||||
newKey := currKey + "[" + strconv.Itoa(i) + "]"
|
||||
flattenToLabels(item, newKey, labels)
|
||||
@@ -168,7 +168,7 @@ func parseDeprecatedConfig(labels map[string]string) (*configuration, error) {
|
||||
|
||||
// Filter unknown nodes and check for deprecated options.
|
||||
config := &configuration{}
|
||||
filterUnknownNodes(reflect.TypeOf(config), node)
|
||||
filterUnknownNodes(reflect.TypeFor[*configuration](), node)
|
||||
|
||||
// If no config remains we can return without error, to allow other loaders to proceed.
|
||||
if node == nil || len(node.Children) == 0 {
|
||||
@@ -271,7 +271,7 @@ func (c *configuration) deprecationNotice(logger zerolog.Logger) bool {
|
||||
if c.Pilot != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Pilot configuration has been removed in v3, please remove all Pilot-related install configuration for Traefik to start." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#pilot")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#pilot")
|
||||
}
|
||||
|
||||
incompatibleCore := c.Core.deprecationNotice(logger)
|
||||
@@ -289,7 +289,7 @@ func (c *core) deprecationNotice(logger zerolog.Logger) bool {
|
||||
if c != nil && c.DefaultRuleSyntax != "" {
|
||||
logger.Error().Msg("`Core.DefaultRuleSyntax` option has been deprecated in v3.4, and will be removed in the next major version." +
|
||||
" Please consider migrating all router rules to v3 syntax." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v3/#rule-syntax")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#router-rule-matchers")
|
||||
}
|
||||
|
||||
return false
|
||||
@@ -319,13 +319,14 @@ func (p *providers) deprecationNotice(logger zerolog.Logger) bool {
|
||||
if p.Marathon != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Marathon provider has been removed in v3, please remove all Marathon-related install configuration for Traefik to start." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#marathon-provider")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#marathon-provider" +
|
||||
"")
|
||||
}
|
||||
|
||||
if p.Rancher != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Rancher provider has been removed in v3, please remove all Rancher-related install configuration for Traefik to start." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#rancher-v1-provider")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#rancher-v1-provider")
|
||||
}
|
||||
|
||||
dockerIncompatible := p.Docker.deprecationNotice(logger)
|
||||
@@ -367,14 +368,14 @@ func (d *docker) deprecationNotice(logger zerolog.Logger) bool {
|
||||
if d.SwarmMode != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Docker provider `swarmMode` option has been removed in v3, please use the Swarm Provider instead." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#docker-docker-swarm")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#swarmmode")
|
||||
}
|
||||
|
||||
if d.TLS != nil && d.TLS.CAOptional != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Docker provider `tls.CAOptional` option has been removed in v3, as TLS client authentication is a server side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634)." +
|
||||
" Please remove all occurrences from the install configuration for Traefik to start." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tlscaoptional")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tlscaoptional")
|
||||
}
|
||||
|
||||
return incompatible
|
||||
@@ -415,7 +416,7 @@ func (e *etcd) deprecationNotice(logger zerolog.Logger) bool {
|
||||
incompatible = true
|
||||
logger.Error().Msg("ETCD provider `tls.CAOptional` option has been removed in v3, as TLS client authentication is a server side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634)." +
|
||||
" Please remove all occurrences from the install configuration for Traefik to start." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tlscaoptional_3")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tlscaoptional_3")
|
||||
}
|
||||
|
||||
return incompatible
|
||||
@@ -436,7 +437,7 @@ func (r *redis) deprecationNotice(logger zerolog.Logger) bool {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Redis provider `tls.CAOptional` option has been removed in v3, as TLS client authentication is a server side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634)." +
|
||||
" Please remove all occurrences from the install configuration for Traefik to start." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tlscaoptional_4")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tlscaoptional_4")
|
||||
}
|
||||
|
||||
return incompatible
|
||||
@@ -457,14 +458,14 @@ func (c *consul) deprecationNotice(logger zerolog.Logger) bool {
|
||||
if c.Namespace != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Consul provider `namespace` option has been removed, please use the `namespaces` option instead." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#consul-provider")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#namespace")
|
||||
}
|
||||
|
||||
if c.TLS != nil && c.TLS.CAOptional != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Consul provider `tls.CAOptional` option has been removed in v3, as TLS client authentication is a server side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634)." +
|
||||
" Please remove all occurrences from the install configuration for Traefik to start." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tlscaoptional_1")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tlscaoptional_1")
|
||||
}
|
||||
|
||||
return incompatible
|
||||
@@ -489,14 +490,14 @@ func (c *consulCatalog) deprecationNotice(logger zerolog.Logger) bool {
|
||||
if c.Namespace != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("ConsulCatalog provider `namespace` option has been removed, please use the `namespaces` option instead." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#consulcatalog-provider")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#namespace_1")
|
||||
}
|
||||
|
||||
if c.Endpoint != nil && c.Endpoint.TLS != nil && c.Endpoint.TLS.CAOptional != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("ConsulCatalog provider `tls.CAOptional` option has been removed in v3, as TLS client authentication is a server side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634)." +
|
||||
" Please remove all occurrences from the install configuration for Traefik to start." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#endpointtlscaoptional")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#endpointtlscaoptional")
|
||||
}
|
||||
|
||||
return incompatible
|
||||
@@ -517,14 +518,14 @@ func (n *nomad) deprecationNotice(logger zerolog.Logger) bool {
|
||||
if n.Namespace != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Nomad provider `namespace` option has been removed, please use the `namespaces` option instead." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#nomad-provider")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#namespace_2")
|
||||
}
|
||||
|
||||
if n.Endpoint != nil && n.Endpoint.TLS != nil && n.Endpoint.TLS.CAOptional != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Nomad provider `tls.CAOptional` option has been removed in v3, as TLS client authentication is a server side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634)." +
|
||||
" Please remove all occurrences from the install configuration for Traefik to start." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#endpointtlscaoptional_1")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#endpointtlscaoptional_1")
|
||||
}
|
||||
|
||||
return incompatible
|
||||
@@ -545,7 +546,7 @@ func (h *http) deprecationNotice(logger zerolog.Logger) bool {
|
||||
incompatible = true
|
||||
logger.Error().Msg("HTTP provider `tls.CAOptional` option has been removed in v3, as TLS client authentication is a server side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634)." +
|
||||
" Please remove all occurrences from the install configuration for Traefik to start." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tlscaoptional_2")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tlscaoptional_2")
|
||||
}
|
||||
|
||||
return incompatible
|
||||
@@ -563,7 +564,7 @@ func (i *ingress) deprecationNotice(logger zerolog.Logger) {
|
||||
if i.DisableIngressClassLookup != nil {
|
||||
logger.Error().Msg("Kubernetes Ingress provider `disableIngressClassLookup` option has been deprecated in v3.1, and will be removed in the next major version." +
|
||||
" Please use the `disableClusterScopeResources` option instead." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v3/#ingressclasslookup")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v3/#ingressclass-lookup")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -581,7 +582,7 @@ func (e *experimental) deprecationNotice(logger zerolog.Logger) bool {
|
||||
if e.HTTP3 != nil {
|
||||
logger.Error().Msg("HTTP3 is not an experimental feature in v3 and the associated enablement has been removed." +
|
||||
" Please remove its usage from the install configuration for Traefik to start." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3-details/#http3")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#http3")
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -589,13 +590,13 @@ func (e *experimental) deprecationNotice(logger zerolog.Logger) bool {
|
||||
if e.KubernetesGateway != nil {
|
||||
logger.Error().Msg("KubernetesGateway provider is not an experimental feature starting with v3.1." +
|
||||
" Please remove its usage from the install configuration." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v3/#gateway-api-kubernetesgateway-provider")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v3/#gateway-api-kubernetesgateway-provider")
|
||||
}
|
||||
|
||||
if e.KubernetesIngressNGINX != nil {
|
||||
logger.Error().Msg("KubernetesIngressNGINX provider is not an experimental feature starting with v3.6.2." +
|
||||
" Please remove its usage from the install configuration." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v3/#ingress-nginx-provider")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v3/#ingress-nginx-provider")
|
||||
}
|
||||
|
||||
return false
|
||||
@@ -622,7 +623,7 @@ func (t *tracing) deprecationNotice(logger zerolog.Logger) bool {
|
||||
if t.SpanNameLimit != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("SpanNameLimit option for Tracing has been removed in v3, as Span names are now of a fixed length." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tracing")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tracing")
|
||||
}
|
||||
|
||||
if t.GlobalAttributes != nil {
|
||||
@@ -630,49 +631,49 @@ func (t *tracing) deprecationNotice(logger zerolog.Logger) bool {
|
||||
|
||||
logger.Error().Msg("`tracing.globalAttributes` option has been deprecated in v3.3, and will be removed in the next major version." +
|
||||
" Please use the `tracing.resourceAttributes` option instead." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v3/#tracing-global-attributes")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v3/#tracing-global-attributes")
|
||||
}
|
||||
|
||||
if t.Jaeger != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Jaeger Tracing backend has been removed in v3, please remove all Jaeger-related Tracing install configuration for Traefik to start." +
|
||||
" In v3, Open Telemetry replaces specific tracing backend implementations, and an collector/exporter can be used to export metrics in a vendor specific format." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tracing")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tracing")
|
||||
}
|
||||
|
||||
if t.Zipkin != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Zipkin Tracing backend has been removed in v3, please remove all Zipkin-related Tracing install configuration for Traefik to start." +
|
||||
" In v3, Open Telemetry replaces specific tracing backend implementations, and an collector/exporter can be used to export metrics in a vendor specific format." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tracing")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tracing")
|
||||
}
|
||||
|
||||
if t.Datadog != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Datadog Tracing backend has been removed in v3, please remove all Datadog-related Tracing install configuration for Traefik to start." +
|
||||
" In v3, Open Telemetry replaces specific tracing backend implementations, and an collector/exporter can be used to export metrics in a vendor specific format." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tracing")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tracing")
|
||||
}
|
||||
|
||||
if t.Instana != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Instana Tracing backend has been removed in v3, please remove all Instana-related Tracing install configuration for Traefik to start." +
|
||||
" In v3, Open Telemetry replaces specific tracing backend implementations, and an collector/exporter can be used to export metrics in a vendor specific format." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tracing")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tracing")
|
||||
}
|
||||
|
||||
if t.Haystack != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Haystack Tracing backend has been removed in v3, please remove all Haystack-related Tracing install configuration for Traefik to start." +
|
||||
" In v3, Open Telemetry replaces specific tracing backend implementations, and an collector/exporter can be used to export metrics in a vendor specific format." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tracing")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tracing")
|
||||
}
|
||||
|
||||
if t.Elastic != nil {
|
||||
incompatible = true
|
||||
logger.Error().Msg("Elastic Tracing backend has been removed in v3, please remove all Elastic-related Tracing install configuration for Traefik to start." +
|
||||
" In v3, Open Telemetry replaces specific tracing backend implementations, and an collector/exporter can be used to export metrics in a vendor specific format." +
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migration/v2-to-v3/#tracing")
|
||||
" For more information please read the migration guide: https://doc.traefik.io/traefik/v3.6/migrate/v2-to-v3-details/#tracing")
|
||||
}
|
||||
|
||||
return incompatible
|
||||
|
||||
@@ -62,7 +62,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"},
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -72,12 +72,12 @@ type Router struct {
|
||||
Rule string `json:"rule,omitempty" toml:"rule,omitempty" yaml:"rule,omitempty"`
|
||||
ParentRefs []string `json:"parentRefs,omitempty" toml:"parentRefs,omitempty" yaml:"parentRefs,omitempty" label:"-" export:"true"`
|
||||
// Deprecated: Please do not use this field and rewrite the router rules to use the v3 syntax.
|
||||
RuleSyntax string `json:"ruleSyntax,omitempty" toml:"ruleSyntax,omitempty" yaml:"ruleSyntax,omitempty" export:"true"`
|
||||
Priority int `json:"priority,omitempty" toml:"priority,omitempty,omitzero" yaml:"priority,omitempty" export:"true"`
|
||||
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
|
||||
Observability *RouterObservabilityConfig `json:"observability,omitempty" toml:"observability,omitempty" yaml:"observability,omitempty" export:"true"`
|
||||
DefaultRule bool `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
|
||||
DeniedEncodedPathCharacters RouterDeniedEncodedPathCharacters `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
|
||||
RuleSyntax string `json:"ruleSyntax,omitempty" toml:"ruleSyntax,omitempty" yaml:"ruleSyntax,omitempty" export:"true"`
|
||||
Priority int `json:"priority,omitempty" toml:"priority,omitempty,omitzero" yaml:"priority,omitempty" export:"true"`
|
||||
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
|
||||
Observability *RouterObservabilityConfig `json:"observability,omitempty" toml:"observability,omitempty" yaml:"observability,omitempty" export:"true"`
|
||||
DefaultRule bool `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
|
||||
DeniedEncodedPathCharacters *RouterDeniedEncodedPathCharacters `json:"-" toml:"-" yaml:"-" label:"-" file:"-" kv:"-"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
@@ -69,6 +69,7 @@ type GrpcWeb struct {
|
||||
type ContentType struct {
|
||||
// AutoDetect specifies whether to let the `Content-Type` header, if it has not been set by the backend,
|
||||
// be automatically set to a value derived from the contents of the response.
|
||||
//
|
||||
// Deprecated: AutoDetect option is deprecated, Content-Type middleware is only meant to be used to enable the content-type detection, please remove any usage of this option.
|
||||
AutoDetect *bool `json:"autoDetect,omitempty" toml:"autoDetect,omitempty" yaml:"autoDetect,omitempty" export:"true"`
|
||||
}
|
||||
@@ -481,6 +482,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/v3.6/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.
|
||||
|
||||
@@ -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"},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ type TCPServersLoadBalancer struct {
|
||||
Servers []TCPServer `json:"servers,omitempty" toml:"servers,omitempty" yaml:"servers,omitempty" label-slice-as-struct:"server" export:"true"`
|
||||
ServersTransport string `json:"serversTransport,omitempty" toml:"serversTransport,omitempty" yaml:"serversTransport,omitempty" export:"true"`
|
||||
// ProxyProtocol holds the PROXY Protocol configuration.
|
||||
//
|
||||
// Deprecated: use ServersTransport to configure ProxyProtocol instead.
|
||||
ProxyProtocol *ProxyProtocol `json:"proxyProtocol,omitempty" toml:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
|
||||
// TerminationDelay, corresponds to the deadline that the proxy sets, after one
|
||||
@@ -95,6 +96,7 @@ type TCPServersLoadBalancer struct {
|
||||
// connection, to close the reading capability as well, hence fully terminating the
|
||||
// connection. It is a duration in milliseconds, defaulting to 100. A negative value
|
||||
// means an infinite deadline (i.e. the reading capability is never closed).
|
||||
//
|
||||
// Deprecated: use ServersTransport to configure the TerminationDelay instead.
|
||||
TerminationDelay *int `json:"terminationDelay,omitempty" toml:"terminationDelay,omitempty" yaml:"terminationDelay,omitempty" export:"true"`
|
||||
HealthCheck *TCPServerHealthCheck `json:"healthCheck,omitempty" toml:"healthCheck,omitempty" yaml:"healthCheck,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
|
||||
|
||||
@@ -26,6 +26,7 @@ type TCPInFlightConn struct {
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TCPIPWhiteList holds the TCP IPWhiteList middleware configuration.
|
||||
//
|
||||
// Deprecated: please use IPAllowList instead.
|
||||
type TCPIPWhiteList struct {
|
||||
// SourceRange defines the allowed IPs (or ranges of allowed IPs by using CIDR notation).
|
||||
|
||||
@@ -1389,7 +1389,11 @@ func (in *Router) DeepCopyInto(out *Router) {
|
||||
*out = new(RouterObservabilityConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
out.DeniedEncodedPathCharacters = in.DeniedEncodedPathCharacters
|
||||
if in.DeniedEncodedPathCharacters != nil {
|
||||
in, out := &in.DeniedEncodedPathCharacters, &out.DeniedEncodedPathCharacters
|
||||
*out = new(RouterDeniedEncodedPathCharacters)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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
|
||||
}
|
||||
|
||||
@@ -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...)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"slices"
|
||||
"sort"
|
||||
"sync"
|
||||
@@ -74,6 +75,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).
|
||||
@@ -91,10 +93,8 @@ 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() {
|
||||
return
|
||||
}
|
||||
if slices.Contains(r.Err, err.Error()) {
|
||||
return
|
||||
}
|
||||
|
||||
r.Err = append(r.Err, err.Error())
|
||||
@@ -112,6 +112,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"`
|
||||
@@ -121,10 +122,8 @@ 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() {
|
||||
return
|
||||
}
|
||||
if slices.Contains(m.Err, err.Error()) {
|
||||
return
|
||||
}
|
||||
|
||||
m.Err = append(m.Err, err.Error())
|
||||
@@ -142,6 +141,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).
|
||||
@@ -157,10 +157,8 @@ 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() {
|
||||
return
|
||||
}
|
||||
if slices.Contains(s.Err, err.Error()) {
|
||||
return
|
||||
}
|
||||
|
||||
s.Err = append(s.Err, err.Error())
|
||||
@@ -197,9 +195,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)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
@@ -49,8 +50,9 @@ 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
|
||||
*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.
|
||||
// It is the caller's responsibility to set the initial status.
|
||||
@@ -61,10 +63,8 @@ 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() {
|
||||
return
|
||||
}
|
||||
if slices.Contains(r.Err, err.Error()) {
|
||||
return
|
||||
}
|
||||
|
||||
r.Err = append(r.Err, err.Error())
|
||||
@@ -81,8 +81,9 @@ 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
|
||||
*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.
|
||||
// It is the caller's responsibility to set the initial status.
|
||||
@@ -96,10 +97,8 @@ 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() {
|
||||
return
|
||||
}
|
||||
if slices.Contains(s.Err, err.Error()) {
|
||||
return
|
||||
}
|
||||
|
||||
s.Err = append(s.Err, err.Error())
|
||||
@@ -135,15 +134,14 @@ func (s *TCPServiceInfo) GetAllStatus() map[string]string {
|
||||
}
|
||||
|
||||
allStatus := make(map[string]string, len(s.serverStatus))
|
||||
for k, v := range s.serverStatus {
|
||||
allStatus[k] = v
|
||||
}
|
||||
maps.Copy(allStatus, s.serverStatus)
|
||||
return allStatus
|
||||
}
|
||||
|
||||
// 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"`
|
||||
@@ -153,10 +151,8 @@ 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() {
|
||||
return
|
||||
}
|
||||
if slices.Contains(m.Err, err.Error()) {
|
||||
return
|
||||
}
|
||||
|
||||
m.Err = append(m.Err, err.Error())
|
||||
|
||||
@@ -54,8 +54,9 @@ 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
|
||||
*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.
|
||||
// It is the caller's responsibility to set the initial status.
|
||||
@@ -66,10 +67,8 @@ 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() {
|
||||
return
|
||||
}
|
||||
if slices.Contains(r.Err, err.Error()) {
|
||||
return
|
||||
}
|
||||
|
||||
r.Err = append(r.Err, err.Error())
|
||||
@@ -86,8 +85,9 @@ 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
|
||||
*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.
|
||||
// It is the caller's responsibility to set the initial status.
|
||||
@@ -98,10 +98,8 @@ 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() {
|
||||
return
|
||||
}
|
||||
if slices.Contains(s.Err, err.Error()) {
|
||||
return
|
||||
}
|
||||
|
||||
s.Err = append(s.Err, err.Error())
|
||||
|
||||
@@ -92,6 +92,16 @@ type EncodedCharacters struct {
|
||||
AllowEncodedHash bool `description:"Defines whether requests with encoded hash characters in the path are allowed." json:"allowEncodedHash,omitempty" toml:"allowEncodedHash,omitempty" yaml:"allowEncodedHash,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
func (ec *EncodedCharacters) SetDefaults() {
|
||||
ec.AllowEncodedSlash = true
|
||||
ec.AllowEncodedBackSlash = true
|
||||
ec.AllowEncodedNullCharacter = true
|
||||
ec.AllowEncodedSemicolon = true
|
||||
ec.AllowEncodedPercent = true
|
||||
ec.AllowEncodedQuestionMark = true
|
||||
ec.AllowEncodedHash = true
|
||||
}
|
||||
|
||||
// HTTP2Config is the HTTP2 configuration of an entry point.
|
||||
type HTTP2Config struct {
|
||||
MaxConcurrentStreams int32 `description:"Specifies the number of concurrent streams per connection that each client is allowed to initiate." json:"maxConcurrentStreams,omitempty" toml:"maxConcurrentStreams,omitempty" yaml:"maxConcurrentStreams,omitempty" export:"true"`
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package static
|
||||
|
||||
// PluginConf holds the plugin configuration.
|
||||
type PluginConf map[string]interface{}
|
||||
type PluginConf map[string]any
|
||||
|
||||
@@ -396,21 +396,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)
|
||||
}
|
||||
}
|
||||
|
||||
logger := logs.NoLevel(log.Logger, zerolog.DebugLevel).With().Str("lib", "lego").Logger()
|
||||
legolog.Logger = logs.NewLogrusWrapper(logger)
|
||||
}
|
||||
|
||||
// ValidateConfiguration validate that configuration is coherent.
|
||||
func (c *Configuration) ValidateConfiguration() error {
|
||||
for name, resolver := range c.CertificatesResolvers {
|
||||
@@ -497,6 +482,21 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
logger := logs.NoLevel(log.Logger, zerolog.DebugLevel).With().Str("lib", "lego").Logger()
|
||||
legolog.Logger = logs.NewLogrusWrapper(logger)
|
||||
}
|
||||
|
||||
func getSafeACMECAServer(caServerSrc string) string {
|
||||
if len(caServerSrc) == 0 {
|
||||
return DefaultAcmeCAServer
|
||||
|
||||
@@ -391,7 +391,7 @@ func (p *PassiveServiceHealthChecker) WrapHandler(ctx context.Context, next http
|
||||
}
|
||||
|
||||
// We need to guarantee that only one goroutine (request) will update the status and create a timer for the target.
|
||||
_, _, _ = p.timersGroup.Do(targetURL, func() (interface{}, error) {
|
||||
_, _, _ = p.timersGroup.Do(targetURL, func() (any, error) {
|
||||
// A timer is already running for this target;
|
||||
// it means that the target is already considered unhealthy.
|
||||
if _, ok := p.timers.Load(targetURL); ok {
|
||||
|
||||
@@ -165,6 +165,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
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ const (
|
||||
// If operation() takes more than MinJobInterval, Reset() is called in NextBackOff().
|
||||
type BackOff struct {
|
||||
*backoff.ExponentialBackOff
|
||||
|
||||
MinJobInterval time.Duration
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
func TestConcatFieldHandler_ServeHTTP(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
existingValue interface{}
|
||||
existingValue any
|
||||
newValue string
|
||||
expectedResult string
|
||||
}{
|
||||
|
||||
@@ -129,7 +129,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 {
|
||||
|
||||
@@ -74,20 +74,6 @@ type Handler struct {
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// AliceConstructor returns an alice.Constructor that wraps the Handler (conditionally) in a middleware chain.
|
||||
func (h *Handler) AliceConstructor() alice.Constructor {
|
||||
return func(next http.Handler) (http.Handler, error) {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
if h == nil {
|
||||
next.ServeHTTP(rw, req)
|
||||
return
|
||||
}
|
||||
|
||||
h.ServeHTTP(rw, req, next)
|
||||
}), nil
|
||||
}
|
||||
}
|
||||
|
||||
// NewHandler creates a new Handler.
|
||||
func NewHandler(ctx context.Context, config *otypes.AccessLog) (*Handler, error) {
|
||||
var file io.WriteCloser = noopCloser{os.Stdout}
|
||||
@@ -185,28 +171,18 @@ func NewHandler(ctx context.Context, config *otypes.AccessLog) (*Handler, error)
|
||||
return logHandler, nil
|
||||
}
|
||||
|
||||
func openAccessLogFile(filePath string) (*os.File, error) {
|
||||
dir := filepath.Dir(filePath)
|
||||
// AliceConstructor returns an alice.Constructor that wraps the Handler (conditionally) in a middleware chain.
|
||||
func (h *Handler) AliceConstructor() alice.Constructor {
|
||||
return func(next http.Handler) (http.Handler, error) {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
if h == nil {
|
||||
next.ServeHTTP(rw, req)
|
||||
return
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
return nil, fmt.Errorf("failed to create log path %s: %w", dir, err)
|
||||
h.ServeHTTP(rw, req, next)
|
||||
}), nil
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o664)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening file %s: %w", filePath, err)
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
// GetLogData gets the request context object that contains logging data.
|
||||
// This creates data as the request passes through the middleware chain.
|
||||
func GetLogData(req *http.Request) *LogData {
|
||||
if ld, ok := req.Context().Value(DataTableKey).(*LogData); ok {
|
||||
return ld
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http.Handler) {
|
||||
@@ -337,23 +313,6 @@ func (h *Handler) Rotate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func silentSplitHostPort(value string) (host, port string) {
|
||||
host, port, err := net.SplitHostPort(value)
|
||||
if err != nil {
|
||||
return value, "-"
|
||||
}
|
||||
return host, port
|
||||
}
|
||||
|
||||
func usernameIfPresent(theURL *url.URL) string {
|
||||
if theURL.User != nil {
|
||||
if name := theURL.User.Username(); name != "" {
|
||||
return name
|
||||
}
|
||||
}
|
||||
return "-"
|
||||
}
|
||||
|
||||
// Logging handler to log frontend name, backend name, and elapsed time.
|
||||
func (h *Handler) logTheRoundTrip(ctx context.Context, logDataTable *LogData) {
|
||||
core := logDataTable.Core
|
||||
@@ -460,6 +419,47 @@ func (h *Handler) keepAccessLog(statusCode, retryAttempts int, duration time.Dur
|
||||
return false
|
||||
}
|
||||
|
||||
// GetLogData gets the request context object that contains logging data.
|
||||
// This creates data as the request passes through the middleware chain.
|
||||
func GetLogData(req *http.Request) *LogData {
|
||||
if ld, ok := req.Context().Value(DataTableKey).(*LogData); ok {
|
||||
return ld
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func openAccessLogFile(filePath string) (*os.File, error) {
|
||||
dir := filepath.Dir(filePath)
|
||||
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
return nil, fmt.Errorf("failed to create log path %s: %w", dir, err)
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o664)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening file %s: %w", filePath, err)
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func silentSplitHostPort(value string) (host, port string) {
|
||||
host, port, err := net.SplitHostPort(value)
|
||||
if err != nil {
|
||||
return value, "-"
|
||||
}
|
||||
return host, port
|
||||
}
|
||||
|
||||
func usernameIfPresent(theURL *url.URL) string {
|
||||
if theURL.User != nil {
|
||||
if name := theURL.User.Username(); name != "" {
|
||||
return name
|
||||
}
|
||||
}
|
||||
return "-"
|
||||
}
|
||||
|
||||
var requestCounter uint64 // Request ID
|
||||
|
||||
func nextRequestCount() uint64 {
|
||||
|
||||
@@ -81,7 +81,7 @@ func (f *GenericCLFLogFormatter) 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
|
||||
|
||||
@@ -15,12 +15,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",
|
||||
@@ -41,7 +41,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",
|
||||
@@ -62,7 +62,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,12 +106,12 @@ func TestGenericCLFLogFormatter_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",
|
||||
@@ -132,7 +132,7 @@ func TestGenericCLFLogFormatter_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",
|
||||
@@ -153,7 +153,7 @@ func TestGenericCLFLogFormatter_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",
|
||||
@@ -199,7 +199,7 @@ func Test_toLog(t *testing.T) {
|
||||
fieldName string
|
||||
defaultValue string
|
||||
quoted bool
|
||||
expectedLog interface{}
|
||||
expectedLog any
|
||||
}{
|
||||
{
|
||||
desc: "Should return int 1",
|
||||
|
||||
@@ -503,32 +503,32 @@ func TestLoggerGenericCLFWithBufferingSize(t *testing.T) {
|
||||
assertValidGenericCLFLogData(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)
|
||||
@@ -541,7 +541,7 @@ func TestLoggerJSON(t *testing.T) {
|
||||
config *otypes.AccessLog
|
||||
tls bool
|
||||
tracing bool
|
||||
expected map[string]func(t *testing.T, value interface{})
|
||||
expected map[string]func(t *testing.T, value any)
|
||||
}{
|
||||
{
|
||||
desc: "default config without tracing",
|
||||
@@ -549,7 +549,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),
|
||||
@@ -589,7 +589,7 @@ func TestLoggerJSON(t *testing.T) {
|
||||
Format: JSONFormat,
|
||||
},
|
||||
tracing: 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),
|
||||
@@ -631,7 +631,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),
|
||||
@@ -676,7 +676,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(),
|
||||
@@ -697,7 +697,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(),
|
||||
@@ -715,7 +715,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(),
|
||||
@@ -742,7 +742,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(""),
|
||||
@@ -768,7 +768,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(""),
|
||||
@@ -794,7 +794,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)
|
||||
|
||||
@@ -808,7 +808,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),
|
||||
@@ -851,7 +851,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)
|
||||
|
||||
|
||||
@@ -96,20 +96,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.crw = &captureResponseWriter{rw: rw}
|
||||
|
||||
return c.crw, newReq
|
||||
}
|
||||
|
||||
func (c *Capture) ResponseSize() int64 {
|
||||
return c.crw.Size()
|
||||
}
|
||||
@@ -127,6 +113,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.crw = &captureResponseWriter{rw: rw}
|
||||
|
||||
return c.crw, newReq
|
||||
}
|
||||
|
||||
type readCounter struct {
|
||||
// source ReadCloser from where the request body is read.
|
||||
source io.ReadCloser
|
||||
|
||||
@@ -167,6 +167,10 @@ func (c *compress) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
c.chooseHandler(c.getCompressionEncoding(acceptEncoding), rw, req)
|
||||
}
|
||||
|
||||
func (c *compress) GetTracingInformation() (string, string) {
|
||||
return c.name, typeName
|
||||
}
|
||||
|
||||
func (c *compress) chooseHandler(typ string, rw http.ResponseWriter, req *http.Request) {
|
||||
switch typ {
|
||||
case zstdName:
|
||||
@@ -180,10 +184,6 @@ func (c *compress) chooseHandler(typ string, rw http.ResponseWriter, req *http.R
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compress) GetTracingInformation() (string, string) {
|
||||
return c.name, typeName
|
||||
}
|
||||
|
||||
func (c *compress) newGzipHandler() (http.Handler, error) {
|
||||
var wrapper func(http.Handler) http.HandlerFunc
|
||||
var err error
|
||||
|
||||
@@ -156,6 +156,7 @@ func (c *CompressionHandler) putCompressionWriter(writer *compressionWriterWrapp
|
||||
|
||||
type compressionWriterWrapper struct {
|
||||
CompressionWriter
|
||||
|
||||
algo string
|
||||
}
|
||||
|
||||
|
||||
@@ -874,10 +874,7 @@ func Test_FlushExcludedContentTypes(t *testing.T) {
|
||||
for len(tb) > 0 {
|
||||
// Write 100 bytes per run
|
||||
// Detection should not be affected (we send 100 bytes)
|
||||
toWrite := 100
|
||||
if toWrite > len(tb) {
|
||||
toWrite = len(tb)
|
||||
}
|
||||
toWrite := min(100, len(tb))
|
||||
|
||||
_, err := rw.Write(tb[:toWrite])
|
||||
require.NoError(t, err)
|
||||
@@ -998,10 +995,7 @@ func Test_FlushIncludedContentTypes(t *testing.T) {
|
||||
for len(tb) > 0 {
|
||||
// Write 100 bytes per run
|
||||
// Detection should not be affected (we send 100 bytes)
|
||||
toWrite := 100
|
||||
if toWrite > len(tb) {
|
||||
toWrite = len(tb)
|
||||
}
|
||||
toWrite := min(100, len(tb))
|
||||
|
||||
_, err := rw.Write(tb[:toWrite])
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -198,16 +199,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.
|
||||
@@ -233,9 +224,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
|
||||
@@ -253,9 +242,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
|
||||
}
|
||||
@@ -288,6 +276,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
|
||||
}
|
||||
|
||||
// codeModifier forwards a response back to the client,
|
||||
// while enforcing a given response code.
|
||||
type codeModifier struct {
|
||||
@@ -343,17 +341,14 @@ func (r *codeModifier) 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
|
||||
}
|
||||
|
||||
@@ -84,18 +84,11 @@ 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 {
|
||||
if idx := strings.Index(clientIP, "%"); idx != -1 {
|
||||
return clientIP[:idx]
|
||||
if before, _, found := strings.Cut(clientIP, "%"); found {
|
||||
return before
|
||||
}
|
||||
return clientIP
|
||||
}
|
||||
@@ -141,6 +134,32 @@ 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)
|
||||
|
||||
if x.notAppendXForwardedFor {
|
||||
r = r.WithContext(httputil.SetNotAppendXFF(r.Context()))
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -189,25 +208,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)
|
||||
|
||||
if x.notAppendXForwardedFor {
|
||||
r = r.WithContext(httputil.SetNotAppendXFF(r.Context()))
|
||||
}
|
||||
|
||||
x.next.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func (x *XForwarded) removeConnectionHeaders(req *http.Request) {
|
||||
var reqUpType string
|
||||
if httpguts.HeaderValuesContainsToken(req.Header[connection], upgrade) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package headermodifier
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
@@ -105,9 +106,7 @@ func TestRequestHeaderModifier(t *testing.T) {
|
||||
handler := NewRequestHeaderModifier(t.Context(), next, test.config, "foo-request-header-modifier")
|
||||
|
||||
req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil)
|
||||
for h, v := range test.requestHeaders {
|
||||
req.Header[h] = v
|
||||
}
|
||||
maps.Copy(req.Header, test.requestHeaders)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
handler.ServeHTTP(resp, req)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package headermodifier
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
@@ -107,9 +108,7 @@ func TestResponseHeaderModifier(t *testing.T) {
|
||||
|
||||
req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
for k, v := range test.responseHeaders {
|
||||
resp.Header()[k] = v
|
||||
}
|
||||
maps.Copy(resp.Header(), test.responseHeaders)
|
||||
|
||||
handler.ServeHTTP(resp, req)
|
||||
|
||||
|
||||
@@ -64,27 +64,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.
|
||||
@@ -134,6 +113,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.
|
||||
|
||||
@@ -65,7 +65,7 @@ func DetailedTracingEnabled(ctx context.Context) bool {
|
||||
}
|
||||
|
||||
// SetStatusErrorf flags the span as in error and log an event.
|
||||
func SetStatusErrorf(ctx context.Context, format string, args ...interface{}) {
|
||||
func SetStatusErrorf(ctx context.Context, format string, args ...any) {
|
||||
if span := trace.SpanFromContext(ctx); span != nil {
|
||||
span.SetStatus(codes.Error, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ func newStatusCodeRecorder(rw http.ResponseWriter, status int) *statusCodeRecord
|
||||
|
||||
type statusCodeRecorder struct {
|
||||
http.ResponseWriter
|
||||
|
||||
status int
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,14 @@ import (
|
||||
)
|
||||
|
||||
type Rediser interface {
|
||||
Eval(ctx context.Context, script string, keys []string, args ...interface{}) *redis.Cmd
|
||||
EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *redis.Cmd
|
||||
Eval(ctx context.Context, script string, keys []string, args ...any) *redis.Cmd
|
||||
EvalSha(ctx context.Context, sha1 string, keys []string, args ...any) *redis.Cmd
|
||||
ScriptExists(ctx context.Context, hashes ...string) *redis.BoolSliceCmd
|
||||
ScriptLoad(ctx context.Context, script string) *redis.StringCmd
|
||||
Del(ctx context.Context, keys ...string) *redis.IntCmd
|
||||
|
||||
EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *redis.Cmd
|
||||
EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *redis.Cmd
|
||||
EvalRO(ctx context.Context, script string, keys []string, args ...any) *redis.Cmd
|
||||
EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...any) *redis.Cmd
|
||||
}
|
||||
|
||||
//nolint:dupword
|
||||
|
||||
@@ -61,10 +61,7 @@ func New(ctx context.Context, next http.Handler, config dynamic.RateLimit, name
|
||||
return nil, fmt.Errorf("getting source extractor: %w", err)
|
||||
}
|
||||
|
||||
burst := config.Burst
|
||||
if burst < 1 {
|
||||
burst = 1
|
||||
}
|
||||
burst := max(config.Burst, 1)
|
||||
|
||||
period := time.Duration(config.Period)
|
||||
if period < 0 {
|
||||
|
||||
@@ -300,11 +300,8 @@ func TestInMemoryRateLimit(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 {
|
||||
@@ -510,11 +507,8 @@ func TestRedisRateLimit(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
|
||||
burst := max(test.config.Burst, 1)
|
||||
|
||||
period := time.Duration(test.config.Period)
|
||||
if period == 0 {
|
||||
@@ -570,7 +564,7 @@ func newMockRedisClient(ttl int) Rediser {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mockRedisClient) EvalSha(ctx context.Context, _ string, keys []string, args ...interface{}) *redis.Cmd {
|
||||
func (m *mockRedisClient) EvalSha(ctx context.Context, _ string, keys []string, args ...any) *redis.Cmd {
|
||||
state := lua.NewState()
|
||||
defer state.Close()
|
||||
|
||||
@@ -641,7 +635,7 @@ func (m *mockRedisClient) EvalSha(ctx context.Context, _ string, keys []string,
|
||||
return cmd
|
||||
}
|
||||
|
||||
var resultSlice []interface{}
|
||||
var resultSlice []any
|
||||
resultTable.ForEach(func(_ lua.LValue, value lua.LValue) {
|
||||
valueNbr, ok := value.(lua.LNumber)
|
||||
if !ok {
|
||||
@@ -661,7 +655,7 @@ func (m *mockRedisClient) EvalSha(ctx context.Context, _ string, keys []string,
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (m *mockRedisClient) Eval(ctx context.Context, script string, keys []string, args ...interface{}) *redis.Cmd {
|
||||
func (m *mockRedisClient) Eval(ctx context.Context, script string, keys []string, args ...any) *redis.Cmd {
|
||||
return m.EvalSha(ctx, script, keys, args...)
|
||||
}
|
||||
|
||||
@@ -677,11 +671,11 @@ func (m *mockRedisClient) Del(ctx context.Context, keys ...string) *redis.IntCmd
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockRedisClient) EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *redis.Cmd {
|
||||
func (m *mockRedisClient) EvalRO(ctx context.Context, script string, keys []string, args ...any) *redis.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockRedisClient) EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *redis.Cmd {
|
||||
func (m *mockRedisClient) EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...any) *redis.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ func (r *redisLimiter) evaluateScript(ctx context.Context, key string) (bool, *t
|
||||
return true, nil, nil
|
||||
}
|
||||
|
||||
params := []interface{}{
|
||||
params := []any{
|
||||
float64(r.rate / 1000000),
|
||||
r.burst,
|
||||
r.ttl,
|
||||
@@ -103,7 +103,7 @@ func (r *redisLimiter) evaluateScript(ctx context.Context, key string) (bool, *t
|
||||
return false, nil, fmt.Errorf("running script: %w", err)
|
||||
}
|
||||
|
||||
values := v.([]interface{})
|
||||
values := v.([]any)
|
||||
ok, err := strconv.ParseBool(values[0].(string))
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("parsing ok value from redis rate lua script: %w", err)
|
||||
|
||||
@@ -56,7 +56,7 @@ func recoverFunc(rw recoveryResponseWriter, req *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
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"math"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -249,10 +250,7 @@ func (r *responseWriter) 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)
|
||||
|
||||
|
||||
@@ -184,13 +184,7 @@ func header(tree *matchersTree, headers ...string) error {
|
||||
key, value := http.CanonicalHeaderKey(headers[0]), headers[1]
|
||||
|
||||
tree.matcher = func(req *http.Request) bool {
|
||||
for _, headerValue := range req.Header[key] {
|
||||
if headerValue == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return slices.Contains(req.Header[key], value)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -205,13 +199,7 @@ func headerRegexp(tree *matchersTree, headers ...string) error {
|
||||
}
|
||||
|
||||
tree.matcher = func(req *http.Request) bool {
|
||||
for _, headerValue := range req.Header[key] {
|
||||
if re.MatchString(headerValue) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return slices.ContainsFunc(req.Header[key], re.MatchString)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -22,7 +22,8 @@ type MatcherFunc func(*http.Request) bool
|
||||
|
||||
// Muxer handles routing with rules.
|
||||
type Muxer struct {
|
||||
routes routes
|
||||
routes routes
|
||||
|
||||
parser SyntaxParser
|
||||
defaultHandler http.Handler
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package tcp
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
@@ -37,13 +38,7 @@ func alpn(tree *matchersTree, protos ...string) error {
|
||||
}
|
||||
|
||||
tree.matcher = func(meta ConnData) bool {
|
||||
for _, alpnProto := range meta.alpnProtos {
|
||||
if alpnProto == proto {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return slices.Contains(meta.alpnProtos, proto)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -56,10 +57,8 @@ func alpnV2(tree *matchersTree, protos ...string) error {
|
||||
|
||||
tree.matcher = func(meta ConnData) bool {
|
||||
for _, proto := range meta.alpnProtos {
|
||||
for _, filter := range protos {
|
||||
if proto == filter {
|
||||
return true
|
||||
}
|
||||
if slices.Contains(protos, proto) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ func GetRulePriority(rule string) int {
|
||||
// AddRoute adds a new route, associated to the given handler, at the given
|
||||
// priority, to the muxer.
|
||||
func (m *Muxer) AddRoute(rule string, syntax string, priority int, handler tcp.Handler) error {
|
||||
var parse interface{}
|
||||
var parse any
|
||||
var err error
|
||||
var matcherFuncs map[string]func(*matchersTree, ...string) error
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
|
||||
func NewAWSWrapper(logger zerolog.Logger) logging.LoggerFunc {
|
||||
if logger.GetLevel() > zerolog.DebugLevel {
|
||||
return func(classification logging.Classification, format string, args ...interface{}) {}
|
||||
return func(classification logging.Classification, format string, args ...any) {}
|
||||
}
|
||||
|
||||
return func(classification logging.Classification, format string, args ...interface{}) {
|
||||
return func(classification logging.Classification, format string, args ...any) {
|
||||
logger.Debug().CallerSkipFrame(2).MsgFunc(msgFunc(args...))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ func NewElasticLogger(logger zerolog.Logger) *ElasticLogger {
|
||||
return &ElasticLogger{logger: logger}
|
||||
}
|
||||
|
||||
func (l ElasticLogger) Debugf(format string, args ...interface{}) {
|
||||
func (l ElasticLogger) Debugf(format string, args ...any) {
|
||||
l.logger.Debug().CallerSkipFrame(1).Msgf(format, args...)
|
||||
}
|
||||
|
||||
func (l ElasticLogger) Errorf(format string, args ...interface{}) {
|
||||
func (l ElasticLogger) Errorf(format string, args ...any) {
|
||||
l.logger.Error().CallerSkipFrame(1).Msgf(format, args...)
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
|
||||
func NewGoKitWrapper(logger zerolog.Logger) kitlog.LoggerFunc {
|
||||
if logger.GetLevel() > zerolog.DebugLevel {
|
||||
return func(args ...interface{}) error { return nil }
|
||||
return func(args ...any) error { return nil }
|
||||
}
|
||||
|
||||
return func(args ...interface{}) error {
|
||||
return func(args ...any) error {
|
||||
logger.Debug().CallerSkipFrame(2).MsgFunc(msgFunc(args...))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -21,26 +21,26 @@ func NewRetryableHTTPLogger(logger zerolog.Logger) *RetryableHTTPLogger {
|
||||
}
|
||||
|
||||
// Error starts a new message with error level.
|
||||
func (l RetryableHTTPLogger) Error(msg string, keysAndValues ...interface{}) {
|
||||
func (l RetryableHTTPLogger) Error(msg string, keysAndValues ...any) {
|
||||
logWithLevel(l.logger.Error().CallerSkipFrame(2), msg, keysAndValues...)
|
||||
}
|
||||
|
||||
// Info starts a new message with info level.
|
||||
func (l RetryableHTTPLogger) Info(msg string, keysAndValues ...interface{}) {
|
||||
func (l RetryableHTTPLogger) Info(msg string, keysAndValues ...any) {
|
||||
logWithLevel(l.logger.Info().CallerSkipFrame(2), msg, keysAndValues...)
|
||||
}
|
||||
|
||||
// Debug starts a new message with debug level.
|
||||
func (l RetryableHTTPLogger) Debug(msg string, keysAndValues ...interface{}) {
|
||||
func (l RetryableHTTPLogger) Debug(msg string, keysAndValues ...any) {
|
||||
logWithLevel(l.logger.Debug().CallerSkipFrame(2), msg, keysAndValues...)
|
||||
}
|
||||
|
||||
// Warn starts a new message with warn level.
|
||||
func (l RetryableHTTPLogger) Warn(msg string, keysAndValues ...interface{}) {
|
||||
func (l RetryableHTTPLogger) Warn(msg string, keysAndValues ...any) {
|
||||
logWithLevel(l.logger.Warn().CallerSkipFrame(2), msg, keysAndValues...)
|
||||
}
|
||||
|
||||
func logWithLevel(ev *zerolog.Event, msg string, kvs ...interface{}) {
|
||||
func logWithLevel(ev *zerolog.Event, msg string, kvs ...any) {
|
||||
if len(kvs)%2 == 0 {
|
||||
for i := 0; i < len(kvs)-1; i += 2 {
|
||||
// The first item of the pair (the key) is supposed to be a string.
|
||||
|
||||
@@ -12,18 +12,18 @@ func NewInstanaLogger(logger zerolog.Logger) *InstanaLogger {
|
||||
return &InstanaLogger{logger: logger}
|
||||
}
|
||||
|
||||
func (l InstanaLogger) Debug(args ...interface{}) {
|
||||
func (l InstanaLogger) Debug(args ...any) {
|
||||
l.logger.Debug().CallerSkipFrame(1).MsgFunc(msgFunc(args...))
|
||||
}
|
||||
|
||||
func (l InstanaLogger) Info(args ...interface{}) {
|
||||
func (l InstanaLogger) Info(args ...any) {
|
||||
l.logger.Info().CallerSkipFrame(1).MsgFunc(msgFunc(args...))
|
||||
}
|
||||
|
||||
func (l InstanaLogger) Warn(args ...interface{}) {
|
||||
func (l InstanaLogger) Warn(args ...any) {
|
||||
l.logger.Warn().CallerSkipFrame(1).MsgFunc(msgFunc(args...))
|
||||
}
|
||||
|
||||
func (l InstanaLogger) Error(args ...interface{}) {
|
||||
func (l InstanaLogger) Error(args ...any) {
|
||||
l.logger.Error().CallerSkipFrame(1).MsgFunc(msgFunc(args...))
|
||||
}
|
||||
|
||||
@@ -12,38 +12,38 @@ func NewLogrusWrapper(logger zerolog.Logger) *LogrusStdWrapper {
|
||||
return &LogrusStdWrapper{logger: logger}
|
||||
}
|
||||
|
||||
func (l LogrusStdWrapper) Print(args ...interface{}) {
|
||||
func (l LogrusStdWrapper) Print(args ...any) {
|
||||
l.logger.Debug().CallerSkipFrame(1).MsgFunc(msgFunc(args...))
|
||||
}
|
||||
|
||||
func (l LogrusStdWrapper) Printf(s string, args ...interface{}) {
|
||||
func (l LogrusStdWrapper) Printf(s string, args ...any) {
|
||||
l.logger.Debug().CallerSkipFrame(1).Msgf(s, args...)
|
||||
}
|
||||
|
||||
func (l LogrusStdWrapper) Println(args ...interface{}) {
|
||||
func (l LogrusStdWrapper) Println(args ...any) {
|
||||
l.logger.Debug().CallerSkipFrame(1).MsgFunc(msgFunc(args...))
|
||||
}
|
||||
|
||||
func (l LogrusStdWrapper) Fatal(args ...interface{}) {
|
||||
func (l LogrusStdWrapper) Fatal(args ...any) {
|
||||
l.logger.Fatal().CallerSkipFrame(1).MsgFunc(msgFunc(args...))
|
||||
}
|
||||
|
||||
func (l LogrusStdWrapper) Fatalf(s string, args ...interface{}) {
|
||||
func (l LogrusStdWrapper) Fatalf(s string, args ...any) {
|
||||
l.logger.Fatal().CallerSkipFrame(1).Msgf(s, args...)
|
||||
}
|
||||
|
||||
func (l LogrusStdWrapper) Fatalln(args ...interface{}) {
|
||||
func (l LogrusStdWrapper) Fatalln(args ...any) {
|
||||
l.logger.Fatal().CallerSkipFrame(1).MsgFunc(msgFunc(args...))
|
||||
}
|
||||
|
||||
func (l LogrusStdWrapper) Panic(args ...interface{}) {
|
||||
func (l LogrusStdWrapper) Panic(args ...any) {
|
||||
l.logger.Panic().CallerSkipFrame(1).MsgFunc(msgFunc(args...))
|
||||
}
|
||||
|
||||
func (l LogrusStdWrapper) Panicf(s string, args ...interface{}) {
|
||||
func (l LogrusStdWrapper) Panicf(s string, args ...any) {
|
||||
l.logger.Panic().CallerSkipFrame(1).Msgf(s, args...)
|
||||
}
|
||||
|
||||
func (l LogrusStdWrapper) Panicln(args ...interface{}) {
|
||||
func (l LogrusStdWrapper) Panicln(args ...any) {
|
||||
l.logger.Panic().CallerSkipFrame(1).MsgFunc(msgFunc(args...))
|
||||
}
|
||||
|
||||
@@ -10,18 +10,18 @@ func NewOxyWrapper(logger zerolog.Logger) *OxyWrapper {
|
||||
return &OxyWrapper{logger: logger}
|
||||
}
|
||||
|
||||
func (l OxyWrapper) Debug(s string, i ...interface{}) {
|
||||
func (l OxyWrapper) Debug(s string, i ...any) {
|
||||
l.logger.Debug().CallerSkipFrame(1).Msgf(s, i...)
|
||||
}
|
||||
|
||||
func (l OxyWrapper) Info(s string, i ...interface{}) {
|
||||
func (l OxyWrapper) Info(s string, i ...any) {
|
||||
l.logger.Info().CallerSkipFrame(1).Msgf(s, i...)
|
||||
}
|
||||
|
||||
func (l OxyWrapper) Warn(s string, i ...interface{}) {
|
||||
func (l OxyWrapper) Warn(s string, i ...any) {
|
||||
l.logger.Warn().CallerSkipFrame(1).Msgf(s, i...)
|
||||
}
|
||||
|
||||
func (l OxyWrapper) Error(s string, i ...interface{}) {
|
||||
func (l OxyWrapper) Error(s string, i ...any) {
|
||||
l.logger.Error().CallerSkipFrame(1).Msgf(s, i...)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -506,7 +506,7 @@ func (lvs otelLabelNamesValues) With(labelValues ...string) otelLabelNamesValues
|
||||
// to the native attribute.KeyValue.
|
||||
func (lvs otelLabelNamesValues) ToLabels() []attribute.KeyValue {
|
||||
labels := make([]attribute.KeyValue, len(lvs)/2)
|
||||
for i := 0; i < len(labels); i++ {
|
||||
for i := range labels {
|
||||
labels[i] = attribute.String(lvs[2*i], lvs[2*i+1])
|
||||
}
|
||||
return labels
|
||||
|
||||
@@ -29,6 +29,15 @@ type Backend interface {
|
||||
Setup(ctx context.Context, serviceName string, sampleRate float64, resourceAttributes map[string]string) (trace.Tracer, io.Closer, error)
|
||||
}
|
||||
|
||||
// Tracer is trace.Tracer with additional properties.
|
||||
type Tracer struct {
|
||||
trace.Tracer
|
||||
|
||||
safeQueryParams []string
|
||||
capturedRequestHeaders []string
|
||||
capturedResponseHeaders []string
|
||||
}
|
||||
|
||||
// NewTracing Creates a Tracing.
|
||||
func NewTracing(ctx context.Context, conf *static.Tracing) (*Tracer, io.Closer, error) {
|
||||
var backend Backend
|
||||
@@ -57,76 +66,6 @@ func NewTracing(ctx context.Context, conf *static.Tracing) (*Tracer, io.Closer,
|
||||
return NewTracer(tr, conf.CapturedRequestHeaders, conf.CapturedResponseHeaders, conf.SafeQueryParams), closer, nil
|
||||
}
|
||||
|
||||
// TracerFromContext extracts the trace.Tracer from the given context.
|
||||
func TracerFromContext(ctx context.Context) *Tracer {
|
||||
// Prevent picking trace.noopSpan tracer.
|
||||
if !trace.SpanContextFromContext(ctx).IsValid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
span := trace.SpanFromContext(ctx)
|
||||
if span != nil && span.TracerProvider() != nil {
|
||||
tracer := span.TracerProvider().Tracer("github.com/traefik/traefik")
|
||||
if tracer, ok := tracer.(*Tracer); ok {
|
||||
return tracer
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExtractCarrierIntoContext reads cross-cutting concerns from the carrier into a Context.
|
||||
func ExtractCarrierIntoContext(ctx context.Context, headers http.Header) context.Context {
|
||||
propagator := otel.GetTextMapPropagator()
|
||||
return propagator.Extract(ctx, propagation.HeaderCarrier(headers))
|
||||
}
|
||||
|
||||
// InjectContextIntoCarrier sets cross-cutting concerns from the request context into the request headers.
|
||||
func InjectContextIntoCarrier(req *http.Request) {
|
||||
propagator := otel.GetTextMapPropagator()
|
||||
propagator.Inject(req.Context(), propagation.HeaderCarrier(req.Header))
|
||||
}
|
||||
|
||||
// Span is trace.Span wrapping the Traefik TracerProvider.
|
||||
type Span struct {
|
||||
trace.Span
|
||||
|
||||
tracerProvider *TracerProvider
|
||||
}
|
||||
|
||||
// TracerProvider returns the span's TraceProvider.
|
||||
func (s Span) TracerProvider() trace.TracerProvider {
|
||||
return s.tracerProvider
|
||||
}
|
||||
|
||||
// TracerProvider is trace.TracerProvider wrapping the Traefik Tracer implementation.
|
||||
type TracerProvider struct {
|
||||
trace.TracerProvider
|
||||
|
||||
tracer *Tracer
|
||||
}
|
||||
|
||||
// Tracer returns the trace.Tracer for the given options.
|
||||
// It returns specifically the Traefik Tracer when requested.
|
||||
func (t TracerProvider) Tracer(name string, options ...trace.TracerOption) trace.Tracer {
|
||||
if name == "github.com/traefik/traefik" {
|
||||
return t.tracer
|
||||
}
|
||||
|
||||
return t.TracerProvider.Tracer(name, options...)
|
||||
}
|
||||
|
||||
// Tracer is trace.Tracer with additional properties.
|
||||
type Tracer struct {
|
||||
trace.Tracer
|
||||
|
||||
safeQueryParams []string
|
||||
capturedRequestHeaders []string
|
||||
capturedResponseHeaders []string
|
||||
}
|
||||
|
||||
// NewTracer builds and configures a new Tracer.
|
||||
func NewTracer(tracer trace.Tracer, capturedRequestHeaders, capturedResponseHeaders, safeQueryParams []string) *Tracer {
|
||||
return &Tracer{
|
||||
@@ -299,6 +238,67 @@ func (t *Tracer) safeURL(originalURL *url.URL) *url.URL {
|
||||
return &redactedURL
|
||||
}
|
||||
|
||||
// Span is trace.Span wrapping the Traefik TracerProvider.
|
||||
type Span struct {
|
||||
trace.Span
|
||||
|
||||
tracerProvider *TracerProvider
|
||||
}
|
||||
|
||||
// TracerProvider returns the span's TraceProvider.
|
||||
func (s Span) TracerProvider() trace.TracerProvider {
|
||||
return s.tracerProvider
|
||||
}
|
||||
|
||||
// TracerProvider is trace.TracerProvider wrapping the Traefik Tracer implementation.
|
||||
type TracerProvider struct {
|
||||
trace.TracerProvider
|
||||
|
||||
tracer *Tracer
|
||||
}
|
||||
|
||||
// Tracer returns the trace.Tracer for the given options.
|
||||
// It returns specifically the Traefik Tracer when requested.
|
||||
func (t TracerProvider) Tracer(name string, options ...trace.TracerOption) trace.Tracer {
|
||||
if name == "github.com/traefik/traefik" {
|
||||
return t.tracer
|
||||
}
|
||||
|
||||
return t.TracerProvider.Tracer(name, options...)
|
||||
}
|
||||
|
||||
// TracerFromContext extracts the trace.Tracer from the given context.
|
||||
func TracerFromContext(ctx context.Context) *Tracer {
|
||||
// Prevent picking trace.noopSpan tracer.
|
||||
if !trace.SpanContextFromContext(ctx).IsValid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
span := trace.SpanFromContext(ctx)
|
||||
if span != nil && span.TracerProvider() != nil {
|
||||
tracer := span.TracerProvider().Tracer("github.com/traefik/traefik")
|
||||
if tracer, ok := tracer.(*Tracer); ok {
|
||||
return tracer
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExtractCarrierIntoContext reads cross-cutting concerns from the carrier into a Context.
|
||||
func ExtractCarrierIntoContext(ctx context.Context, headers http.Header) context.Context {
|
||||
propagator := otel.GetTextMapPropagator()
|
||||
return propagator.Extract(ctx, propagation.HeaderCarrier(headers))
|
||||
}
|
||||
|
||||
// InjectContextIntoCarrier sets cross-cutting concerns from the request context into the request headers.
|
||||
func InjectContextIntoCarrier(req *http.Request) {
|
||||
propagator := otel.GetTextMapPropagator()
|
||||
propagator.Inject(req.Context(), propagation.HeaderCarrier(req.Header))
|
||||
}
|
||||
|
||||
func proto(proto string) string {
|
||||
switch proto {
|
||||
case "HTTP/1.0":
|
||||
|
||||
@@ -492,6 +492,8 @@ func resourceAttributes(traces ptrace.Traces) map[string]string {
|
||||
}
|
||||
|
||||
// mainSpan gets the main span from traces (assumes single span for testing).
|
||||
//
|
||||
//nolint:unqueryvet // False positive: This is OTel trace iteration, not SQLBoiler.
|
||||
func mainSpan(traces ptrace.Traces) ptrace.Span {
|
||||
for _, resourceSpans := range traces.ResourceSpans().All() {
|
||||
for _, scopeSpans := range resourceSpans.ScopeSpans().All() {
|
||||
|
||||
@@ -18,7 +18,7 @@ type pluginMiddleware interface {
|
||||
}
|
||||
|
||||
type middlewareBuilder interface {
|
||||
newMiddleware(config map[string]interface{}, middlewareName string) (pluginMiddleware, error)
|
||||
newMiddleware(config map[string]any, middlewareName string) (pluginMiddleware, error)
|
||||
}
|
||||
|
||||
// Builder is a plugin builder.
|
||||
@@ -110,7 +110,7 @@ func NewBuilder(manager *Manager, plugins map[string]Descriptor, localPlugins ma
|
||||
}
|
||||
|
||||
// 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 definitions in the static configuration: %s", pName)
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ func TestPluginManager_ReadManifest(t *testing.T) {
|
||||
Type: "middleware",
|
||||
Import: "github.com/test/plugin",
|
||||
Summary: "A test plugin",
|
||||
TestData: map[string]interface{}{
|
||||
TestData: map[string]any{
|
||||
"test": "data",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func newWasmMiddlewareBuilder(goPath, moduleName, wasmPath string, settings Sett
|
||||
return &wasmMiddlewareBuilder{path: path, cache: cache, settings: settings}, nil
|
||||
}
|
||||
|
||||
func (b wasmMiddlewareBuilder) newMiddleware(config map[string]interface{}, middlewareName string) (pluginMiddleware, error) {
|
||||
func (b wasmMiddlewareBuilder) newMiddleware(config map[string]any, middlewareName string) (pluginMiddleware, error) {
|
||||
return &WasmMiddleware{
|
||||
middlewareName: middlewareName,
|
||||
config: reflect.ValueOf(config),
|
||||
@@ -114,7 +114,7 @@ func (b *wasmMiddlewareBuilder) buildMiddleware(ctx context.Context, next http.H
|
||||
|
||||
i := cfg.Interface()
|
||||
if i != nil {
|
||||
config, ok := i.(map[string]interface{})
|
||||
config, ok := i.(map[string]any)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("could not type assert config: %T", i)
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@ func TestSettingsWithoutSocket(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
desc string
|
||||
getSettings func(t *testing.T) (Settings, map[string]interface{})
|
||||
getSettings func(t *testing.T) (Settings, map[string]any)
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
desc: "mounts path",
|
||||
getSettings: func(t *testing.T) (Settings, map[string]interface{}) {
|
||||
getSettings: func(t *testing.T) (Settings, map[string]any) {
|
||||
t.Helper()
|
||||
|
||||
tempDir := t.TempDir()
|
||||
@@ -42,7 +42,7 @@ func TestSettingsWithoutSocket(t *testing.T) {
|
||||
|
||||
return Settings{Mounts: []string{
|
||||
tempDir,
|
||||
}}, map[string]interface{}{
|
||||
}}, map[string]any{
|
||||
"file": filePath,
|
||||
}
|
||||
},
|
||||
@@ -50,7 +50,7 @@ func TestSettingsWithoutSocket(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "mounts src to dest",
|
||||
getSettings: func(t *testing.T) (Settings, map[string]interface{}) {
|
||||
getSettings: func(t *testing.T) (Settings, map[string]any) {
|
||||
t.Helper()
|
||||
|
||||
tempDir := t.TempDir()
|
||||
@@ -60,7 +60,7 @@ func TestSettingsWithoutSocket(t *testing.T) {
|
||||
|
||||
return Settings{Mounts: []string{
|
||||
tempDir + ":/tmp",
|
||||
}}, map[string]interface{}{
|
||||
}}, map[string]any{
|
||||
"file": "/tmp/hello.txt",
|
||||
}
|
||||
},
|
||||
@@ -68,11 +68,11 @@ func TestSettingsWithoutSocket(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "one env",
|
||||
getSettings: func(t *testing.T) (Settings, map[string]interface{}) {
|
||||
getSettings: func(t *testing.T) (Settings, map[string]any) {
|
||||
t.Helper()
|
||||
|
||||
envs := []string{"PLUGIN_TEST"}
|
||||
return Settings{Envs: envs}, map[string]interface{}{
|
||||
return Settings{Envs: envs}, map[string]any{
|
||||
"envs": envs,
|
||||
}
|
||||
},
|
||||
@@ -80,11 +80,11 @@ func TestSettingsWithoutSocket(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "two env",
|
||||
getSettings: func(t *testing.T) (Settings, map[string]interface{}) {
|
||||
getSettings: func(t *testing.T) (Settings, map[string]any) {
|
||||
t.Helper()
|
||||
|
||||
envs := []string{"PLUGIN_TEST", "PLUGIN_TEST_B"}
|
||||
return Settings{Envs: envs}, map[string]interface{}{
|
||||
return Settings{Envs: envs}, map[string]any{
|
||||
"envs": envs,
|
||||
}
|
||||
},
|
||||
|
||||
@@ -46,7 +46,7 @@ func newYaegiMiddlewareBuilder(i *interp.Interpreter, basePkg, imp string) (*yae
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b yaegiMiddlewareBuilder) newMiddleware(config map[string]interface{}, middlewareName string) (pluginMiddleware, error) {
|
||||
func (b yaegiMiddlewareBuilder) newMiddleware(config map[string]any, middlewareName string) (pluginMiddleware, error) {
|
||||
vConfig, err := b.createConfig(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -80,7 +80,7 @@ func (b yaegiMiddlewareBuilder) newHandler(ctx context.Context, next http.Handle
|
||||
return handler, nil
|
||||
}
|
||||
|
||||
func (b yaegiMiddlewareBuilder) createConfig(config map[string]interface{}) (reflect.Value, error) {
|
||||
func (b yaegiMiddlewareBuilder) createConfig(config map[string]any) (reflect.Value, error) {
|
||||
results := b.fnCreateConfig.Call(nil)
|
||||
if len(results) != 1 {
|
||||
return reflect.Value{}, fmt.Errorf("invalid number of return for the CreateConfig function: %d", len(results))
|
||||
|
||||
@@ -138,7 +138,7 @@ func verifyMiddlewareWorks(t *testing.T, builder *yaegiMiddlewareBuilder) {
|
||||
t.Helper()
|
||||
// Create a middleware instance - this will call the plugin's New() function
|
||||
// which uses unsafe/syscall, proving they work
|
||||
middleware, err := builder.newMiddleware(map[string]interface{}{
|
||||
middleware, err := builder.newMiddleware(map[string]any{
|
||||
"message": "test",
|
||||
}, "test-middleware")
|
||||
require.NoError(t, err, "Should be able to create middleware that uses unsafe/syscall")
|
||||
|
||||
@@ -25,7 +25,7 @@ type PP interface {
|
||||
}
|
||||
|
||||
type _PP struct {
|
||||
IValue interface{}
|
||||
IValue any
|
||||
WInit func() error
|
||||
WProvide func(cfgChan chan<- json.Marshaler) error
|
||||
WStop func() error
|
||||
@@ -53,7 +53,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)
|
||||
}
|
||||
@@ -82,7 +82,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), "-", "_")
|
||||
|
||||
+10
-10
@@ -42,16 +42,16 @@ type LocalDescriptor struct {
|
||||
|
||||
// Manifest The plugin manifest.
|
||||
type Manifest struct {
|
||||
DisplayName string `yaml:"displayName"`
|
||||
Type string `yaml:"type"`
|
||||
Runtime string `yaml:"runtime"`
|
||||
WasmPath string `yaml:"wasmPath"`
|
||||
Import string `yaml:"import"`
|
||||
BasePkg string `yaml:"basePkg"`
|
||||
Compatibility string `yaml:"compatibility"`
|
||||
Summary string `yaml:"summary"`
|
||||
UseUnsafe bool `yaml:"useUnsafe"`
|
||||
TestData map[string]interface{} `yaml:"testData"`
|
||||
DisplayName string `yaml:"displayName"`
|
||||
Type string `yaml:"type"`
|
||||
Runtime string `yaml:"runtime"`
|
||||
WasmPath string `yaml:"wasmPath"`
|
||||
Import string `yaml:"import"`
|
||||
BasePkg string `yaml:"basePkg"`
|
||||
Compatibility string `yaml:"compatibility"`
|
||||
Summary string `yaml:"summary"`
|
||||
UseUnsafe bool `yaml:"useUnsafe"`
|
||||
TestData map[string]any `yaml:"testData"`
|
||||
}
|
||||
|
||||
// IsYaegiPlugin returns true if the plugin is a Yaegi plugin.
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"maps"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
@@ -30,6 +31,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()
|
||||
@@ -122,8 +169,7 @@ func (s *LocalStore) listenSaveAction(routinesPool *safe.Pool) {
|
||||
logger.Error().Err(err).Send()
|
||||
}
|
||||
|
||||
err = os.WriteFile(s.filename, data, 0o600)
|
||||
if err != nil {
|
||||
if err := os.WriteFile(s.filename, data, 0o600); err != nil {
|
||||
logger.Error().Err(err).Send()
|
||||
}
|
||||
}
|
||||
@@ -133,55 +179,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)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package acme
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ func (a *Configuration) SetDefaults() {
|
||||
// CertAndStore allows mapping a TLS certificate to a TLS store.
|
||||
type CertAndStore struct {
|
||||
Certificate
|
||||
|
||||
Store string
|
||||
}
|
||||
|
||||
@@ -129,6 +130,7 @@ type TLSChallenge struct {
|
||||
// Provider holds configurations of the provider.
|
||||
type Provider struct {
|
||||
*Configuration
|
||||
|
||||
ResolverName string
|
||||
Store Store `json:"store,omitempty" toml:"store,omitempty" yaml:"store,omitempty"`
|
||||
|
||||
|
||||
@@ -150,13 +150,6 @@ func NewProviderAggregator(conf static.Providers) *ProviderAggregator {
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *ProviderAggregator) quietAddProvider(provider provider.Provider) {
|
||||
err := p.AddProvider(provider)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("Error while initializing provider %T", provider)
|
||||
}
|
||||
}
|
||||
|
||||
// AddProvider adds a provider in the providers map.
|
||||
func (p *ProviderAggregator) AddProvider(provider provider.Provider) error {
|
||||
err := provider.Init()
|
||||
@@ -202,6 +195,13 @@ func (p *ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, p
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ProviderAggregator) quietAddProvider(provider provider.Provider) {
|
||||
err := p.AddProvider(provider)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("Error while initializing provider %T", provider)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProviderAggregator) launchProvider(configurationChan chan<- dynamic.Message, pool *safe.Pool, prd provider.Provider) {
|
||||
jsonConf, err := redactor.RemoveCredentials(prd)
|
||||
if err != nil {
|
||||
|
||||
@@ -401,9 +401,7 @@ func MakeDefaultRuleTemplate(defaultRule string, funcMap template.FuncMap) (*tem
|
||||
defaultFuncMap := sprig.TxtFuncMap()
|
||||
defaultFuncMap["normalize"] = Normalize
|
||||
|
||||
for k, fn := range funcMap {
|
||||
defaultFuncMap[k] = fn
|
||||
}
|
||||
maps.Copy(defaultFuncMap, funcMap)
|
||||
|
||||
return template.New("defaultRule").Funcs(defaultFuncMap).Parse(defaultRule)
|
||||
}
|
||||
@@ -458,7 +456,7 @@ func BuildUDPRouterConfiguration(ctx context.Context, configuration *dynamic.UDP
|
||||
}
|
||||
|
||||
// BuildRouterConfiguration builds a router configuration.
|
||||
func BuildRouterConfiguration(ctx context.Context, configuration *dynamic.HTTPConfiguration, defaultRouterName string, defaultRuleTpl *template.Template, model interface{}) {
|
||||
func BuildRouterConfiguration(ctx context.Context, configuration *dynamic.HTTPConfiguration, defaultRouterName string, defaultRuleTpl *template.Template, model any) {
|
||||
if len(configuration.Routers) == 0 {
|
||||
if len(configuration.Services) > 1 {
|
||||
log.Ctx(ctx).Info().Msg("Could not create a router for the container: too many services")
|
||||
|
||||
@@ -24,7 +24,7 @@ func MatchLabels(labels map[string]string, expr string) (bool, error) {
|
||||
NOT: notLabelFunc,
|
||||
OR: orLabelFunc,
|
||||
},
|
||||
Functions: map[string]interface{}{
|
||||
Functions: map[string]any{
|
||||
"Label": labelFn,
|
||||
"LabelRegex": labelRegexFn,
|
||||
},
|
||||
|
||||
@@ -25,7 +25,7 @@ func MatchTags(tags []string, expr string) (bool, error) {
|
||||
NOT: notTagFunc,
|
||||
OR: orTagFunc,
|
||||
},
|
||||
Functions: map[string]interface{}{
|
||||
Functions: map[string]any{
|
||||
"Tag": tagFn,
|
||||
"TagRegex": tagRegexFn,
|
||||
},
|
||||
|
||||
@@ -248,6 +248,11 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Namespace returns the namespace of the ConsulCatalog provider.
|
||||
func (p *Provider) Namespace() string {
|
||||
return p.namespace
|
||||
}
|
||||
|
||||
func (p *Provider) loadConfiguration(ctx context.Context, certInfo *connectCert, configurationChan chan<- dynamic.Message) error {
|
||||
data, err := p.getConsulServicesData(ctx)
|
||||
if err != nil {
|
||||
@@ -388,12 +393,12 @@ func (p *Provider) fetchService(ctx context.Context, name string, connectEnabled
|
||||
// watchServices watches for update events of the services list and statuses,
|
||||
// and transmits them to the caller through the p.watchServicesChan.
|
||||
func (p *Provider) watchServices(ctx context.Context) error {
|
||||
servicesWatcher, err := watch.Parse(map[string]interface{}{"type": "services"})
|
||||
servicesWatcher, err := watch.Parse(map[string]any{"type": "services"})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create services watcher plan: %w", err)
|
||||
}
|
||||
|
||||
servicesWatcher.HybridHandler = func(_ watch.BlockingParamVal, _ interface{}) {
|
||||
servicesWatcher.HybridHandler = func(_ watch.BlockingParamVal, _ any) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case p.watchServicesChan <- struct{}{}:
|
||||
@@ -402,12 +407,12 @@ func (p *Provider) watchServices(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
checksWatcher, err := watch.Parse(map[string]interface{}{"type": "checks"})
|
||||
checksWatcher, err := watch.Parse(map[string]any{"type": "checks"})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create checks watcher plan: %w", err)
|
||||
}
|
||||
|
||||
checksWatcher.HybridHandler = func(_ watch.BlockingParamVal, _ interface{}) {
|
||||
checksWatcher.HybridHandler = func(_ watch.BlockingParamVal, _ any) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case p.watchServicesChan <- struct{}{}:
|
||||
@@ -447,66 +452,11 @@ func (p *Provider) watchServices(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
func rootsWatchHandler(ctx context.Context, dest chan<- []string) func(watch.BlockingParamVal, interface{}) {
|
||||
return func(_ watch.BlockingParamVal, raw interface{}) {
|
||||
if raw == nil {
|
||||
log.Ctx(ctx).Error().Msg("Root certificate watcher called with nil")
|
||||
return
|
||||
}
|
||||
|
||||
v, ok := raw.(*api.CARootList)
|
||||
if !ok || v == nil {
|
||||
log.Ctx(ctx).Error().Msg("Invalid result for root certificate watcher")
|
||||
return
|
||||
}
|
||||
|
||||
roots := make([]string, 0, len(v.Roots))
|
||||
for _, root := range v.Roots {
|
||||
roots = append(roots, root.RootCertPEM)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case dest <- roots:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type keyPair struct {
|
||||
cert string
|
||||
key string
|
||||
}
|
||||
|
||||
func leafWatcherHandler(ctx context.Context, dest chan<- keyPair) func(watch.BlockingParamVal, interface{}) {
|
||||
return func(_ watch.BlockingParamVal, raw interface{}) {
|
||||
if raw == nil {
|
||||
log.Ctx(ctx).Error().Msg("Leaf certificate watcher called with nil")
|
||||
return
|
||||
}
|
||||
|
||||
v, ok := raw.(*api.LeafCert)
|
||||
if !ok || v == nil {
|
||||
log.Ctx(ctx).Error().Msg("Invalid result for leaf certificate watcher")
|
||||
return
|
||||
}
|
||||
|
||||
kp := keyPair{
|
||||
cert: v.CertPEM,
|
||||
key: v.PrivateKeyPEM,
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case dest <- kp:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// watchConnectTLS watches for updates of the root certificate or the leaf
|
||||
// certificate, and transmits them to the caller via p.certChan.
|
||||
func (p *Provider) watchConnectTLS(ctx context.Context) error {
|
||||
leafChan := make(chan keyPair)
|
||||
leafWatcher, err := watch.Parse(map[string]interface{}{
|
||||
leafWatcher, err := watch.Parse(map[string]any{
|
||||
"type": "connect_leaf",
|
||||
"service": p.ServiceName,
|
||||
})
|
||||
@@ -516,7 +466,7 @@ func (p *Provider) watchConnectTLS(ctx context.Context) error {
|
||||
leafWatcher.HybridHandler = leafWatcherHandler(ctx, leafChan)
|
||||
|
||||
rootsChan := make(chan []string)
|
||||
rootsWatcher, err := watch.Parse(map[string]interface{}{
|
||||
rootsWatcher, err := watch.Parse(map[string]any{
|
||||
"type": "connect_roots",
|
||||
})
|
||||
if err != nil {
|
||||
@@ -596,6 +546,61 @@ func (p *Provider) includesHealthStatus(status string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func rootsWatchHandler(ctx context.Context, dest chan<- []string) func(watch.BlockingParamVal, any) {
|
||||
return func(_ watch.BlockingParamVal, raw any) {
|
||||
if raw == nil {
|
||||
log.Ctx(ctx).Error().Msg("Root certificate watcher called with nil")
|
||||
return
|
||||
}
|
||||
|
||||
v, ok := raw.(*api.CARootList)
|
||||
if !ok || v == nil {
|
||||
log.Ctx(ctx).Error().Msg("Invalid result for root certificate watcher")
|
||||
return
|
||||
}
|
||||
|
||||
roots := make([]string, 0, len(v.Roots))
|
||||
for _, root := range v.Roots {
|
||||
roots = append(roots, root.RootCertPEM)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case dest <- roots:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type keyPair struct {
|
||||
cert string
|
||||
key string
|
||||
}
|
||||
|
||||
func leafWatcherHandler(ctx context.Context, dest chan<- keyPair) func(watch.BlockingParamVal, any) {
|
||||
return func(_ watch.BlockingParamVal, raw any) {
|
||||
if raw == nil {
|
||||
log.Ctx(ctx).Error().Msg("Leaf certificate watcher called with nil")
|
||||
return
|
||||
}
|
||||
|
||||
v, ok := raw.(*api.LeafCert)
|
||||
if !ok || v == nil {
|
||||
log.Ctx(ctx).Error().Msg("Invalid result for leaf certificate watcher")
|
||||
return
|
||||
}
|
||||
|
||||
kp := keyPair{
|
||||
cert: v.CertPEM,
|
||||
key: v.PrivateKeyPEM,
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case dest <- kp:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createClient(namespace string, endpoint *EndpointConfig) (*api.Client, error) {
|
||||
config := api.Config{
|
||||
Address: endpoint.Address,
|
||||
@@ -647,8 +652,3 @@ func repeatSend(ctx context.Context, interval time.Duration, c chan<- struct{})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Namespace returns the namespace of the ConsulCatalog provider.
|
||||
func (p *Provider) Namespace() string {
|
||||
return p.namespace
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
type DynConfBuilder struct {
|
||||
Shared
|
||||
|
||||
apiClient client.APIClient
|
||||
swarm bool
|
||||
}
|
||||
|
||||
@@ -50,10 +50,6 @@ func (p *Provider) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Provider) createClient(ctx context.Context) (*client.Client, error) {
|
||||
return createClient(ctx, p.ClientConfig)
|
||||
}
|
||||
|
||||
// Provide allows the docker provider to provide configurations to traefik using the given configuration channel.
|
||||
func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
||||
pool.GoCtx(func(routineCtx context.Context) {
|
||||
@@ -160,6 +156,10 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Provider) createClient(ctx context.Context) (*client.Client, error) {
|
||||
return createClient(ctx, p.ClientConfig)
|
||||
}
|
||||
|
||||
func (p *Provider) listContainers(ctx context.Context, dockerClient client.ContainerAPIClient) ([]dockerData, error) {
|
||||
containerList, err := dockerClient.ContainerList(ctx, container.ListOptions{
|
||||
All: true,
|
||||
|
||||
@@ -54,10 +54,6 @@ func (p *SwarmProvider) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *SwarmProvider) createClient(ctx context.Context) (*client.Client, error) {
|
||||
return createClient(ctx, p.ClientConfig)
|
||||
}
|
||||
|
||||
// Provide allows the docker provider to provide configurations to traefik using the given configuration channel.
|
||||
func (p *SwarmProvider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
||||
pool.GoCtx(func(routineCtx context.Context) {
|
||||
@@ -154,6 +150,10 @@ func (p *SwarmProvider) Provide(configurationChan chan<- dynamic.Message, pool *
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *SwarmProvider) createClient(ctx context.Context) (*client.Client, error) {
|
||||
return createClient(ctx, p.ClientConfig)
|
||||
}
|
||||
|
||||
func (p *SwarmProvider) listServices(ctx context.Context, dockerClient client.APIClient) ([]dockerData, error) {
|
||||
logger := log.Ctx(ctx)
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
type fakeTasksClient struct {
|
||||
dockerclient.APIClient
|
||||
|
||||
tasks []swarmtypes.Task
|
||||
container containertypes.InspectResponse
|
||||
err error
|
||||
@@ -27,6 +28,7 @@ func (c *fakeTasksClient) ContainerInspect(ctx context.Context, container string
|
||||
|
||||
type fakeServicesClient struct {
|
||||
dockerclient.APIClient
|
||||
|
||||
dockerVersion string
|
||||
networks []networktypes.Summary
|
||||
nodes []swarmtypes.Node
|
||||
|
||||
+35
-35
@@ -104,41 +104,6 @@ func (p *Provider) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Provider) createClient(ctx context.Context, logger zerolog.Logger) (*awsClient, error) {
|
||||
optFns := []func(*config.LoadOptions) error{
|
||||
config.WithLogger(logs.NewAWSWrapper(logger)),
|
||||
}
|
||||
if p.Region != "" {
|
||||
optFns = append(optFns, config.WithRegion(p.Region))
|
||||
} else {
|
||||
logger.Info().Msg("No region provided, will retrieve region from the EC2 Metadata service")
|
||||
optFns = append(optFns, config.WithEC2IMDSRegion())
|
||||
}
|
||||
|
||||
if p.AccessKeyID != "" && p.SecretAccessKey != "" {
|
||||
// From https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/configure-gosdk.html#specify-credentials-programmatically:
|
||||
// "If you explicitly provide credentials, as in this example, the SDK uses only those credentials."
|
||||
// this makes sure that user-defined credentials always have the highest priority
|
||||
staticCreds := aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(p.AccessKeyID, p.SecretAccessKey, ""))
|
||||
optFns = append(optFns, config.WithCredentialsProvider(staticCreds))
|
||||
|
||||
// If the access key and secret access key are not provided, config.LoadDefaultConfig
|
||||
// will look for the credentials in the default credential chain.
|
||||
// See https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/configure-gosdk.html#specifying-credentials.
|
||||
}
|
||||
|
||||
cfg, err := config.LoadDefaultConfig(ctx, optFns...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &awsClient{
|
||||
ecs.NewFromConfig(cfg),
|
||||
ec2.NewFromConfig(cfg),
|
||||
ssm.NewFromConfig(cfg),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Provide configuration to traefik from ECS.
|
||||
func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
||||
pool.GoCtx(func(routineCtx context.Context) {
|
||||
@@ -185,6 +150,41 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Provider) createClient(ctx context.Context, logger zerolog.Logger) (*awsClient, error) {
|
||||
optFns := []func(*config.LoadOptions) error{
|
||||
config.WithLogger(logs.NewAWSWrapper(logger)),
|
||||
}
|
||||
if p.Region != "" {
|
||||
optFns = append(optFns, config.WithRegion(p.Region))
|
||||
} else {
|
||||
logger.Info().Msg("No region provided, will retrieve region from the EC2 Metadata service")
|
||||
optFns = append(optFns, config.WithEC2IMDSRegion())
|
||||
}
|
||||
|
||||
if p.AccessKeyID != "" && p.SecretAccessKey != "" {
|
||||
// From https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/configure-gosdk.html#specify-credentials-programmatically:
|
||||
// "If you explicitly provide credentials, as in this example, the SDK uses only those credentials."
|
||||
// this makes sure that user-defined credentials always have the highest priority
|
||||
staticCreds := aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(p.AccessKeyID, p.SecretAccessKey, ""))
|
||||
optFns = append(optFns, config.WithCredentialsProvider(staticCreds))
|
||||
|
||||
// If the access key and secret access key are not provided, config.LoadDefaultConfig
|
||||
// will look for the credentials in the default credential chain.
|
||||
// See https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/configure-gosdk.html#specifying-credentials.
|
||||
}
|
||||
|
||||
cfg, err := config.LoadDefaultConfig(ctx, optFns...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &awsClient{
|
||||
ecs.NewFromConfig(cfg),
|
||||
ec2.NewFromConfig(cfg),
|
||||
ssm.NewFromConfig(cfg),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Provider) loadConfiguration(ctx context.Context, client *awsClient, configurationChan chan<- dynamic.Message) error {
|
||||
instances, err := p.listInstances(ctx, client)
|
||||
if err != nil {
|
||||
|
||||
+76
-77
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
@@ -112,6 +113,51 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateConfiguration creates a provider configuration from content using templating.
|
||||
func (p *Provider) CreateConfiguration(ctx context.Context, filename string, funcMap template.FuncMap, templateObjects any) (*dynamic.Configuration, error) {
|
||||
tmplContent, err := readFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading configuration file: %s - %w", filename, err)
|
||||
}
|
||||
|
||||
defaultFuncMap := sprig.TxtFuncMap()
|
||||
defaultFuncMap["normalize"] = provider.Normalize
|
||||
defaultFuncMap["split"] = strings.Split
|
||||
maps.Copy(defaultFuncMap, funcMap)
|
||||
|
||||
tmpl := template.New(p.Filename).Funcs(defaultFuncMap)
|
||||
|
||||
_, err = tmpl.Parse(tmplContent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var buffer bytes.Buffer
|
||||
err = tmpl.Execute(&buffer, templateObjects)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
renderedTemplate := buffer.String()
|
||||
if p.DebugLogGeneratedTemplate {
|
||||
logger := log.Ctx(ctx)
|
||||
logger.Debug().Msgf("Template content: %s", tmplContent)
|
||||
logger.Debug().Msgf("Rendering results: %s", renderedTemplate)
|
||||
}
|
||||
|
||||
return p.decodeConfiguration(filename, renderedTemplate)
|
||||
}
|
||||
|
||||
// DecodeConfiguration Decodes a *types.Configuration from a content.
|
||||
func (p *Provider) DecodeConfiguration(filename string) (*dynamic.Configuration, error) {
|
||||
content, err := readFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading configuration file: %s - %w", filename, err)
|
||||
}
|
||||
|
||||
return p.decodeConfiguration(filename, content)
|
||||
}
|
||||
|
||||
func (p *Provider) addWatcher(pool *safe.Pool, items []string, configurationChan chan<- dynamic.Message, callback func(chan<- dynamic.Message) error) error {
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
@@ -185,13 +231,6 @@ func (p *Provider) buildConfiguration() (*dynamic.Configuration, error) {
|
||||
return nil, errors.New("error using file configuration provider, neither filename nor directory is defined")
|
||||
}
|
||||
|
||||
func sendConfigToChannel(configurationChan chan<- dynamic.Message, configuration *dynamic.Configuration) {
|
||||
configurationChan <- dynamic.Message{
|
||||
ProviderName: "file",
|
||||
Configuration: configuration,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Provider) loadFileConfig(ctx context.Context, filename string, parseTemplate bool) (*dynamic.Configuration, error) {
|
||||
var err error
|
||||
var configuration *dynamic.Configuration
|
||||
@@ -337,29 +376,6 @@ func (p *Provider) loadFileConfig(ctx context.Context, filename string, parseTem
|
||||
return configuration, nil
|
||||
}
|
||||
|
||||
func flattenCertificates(ctx context.Context, tlsConfig *dynamic.TLSConfiguration) []*tls.CertAndStores {
|
||||
var certs []*tls.CertAndStores
|
||||
for _, cert := range tlsConfig.Certificates {
|
||||
content, err := cert.Certificate.CertFile.Read()
|
||||
if err != nil {
|
||||
log.Ctx(ctx).Error().Err(err).Send()
|
||||
continue
|
||||
}
|
||||
cert.Certificate.CertFile = types.FileOrContent(string(content))
|
||||
|
||||
content, err = cert.Certificate.KeyFile.Read()
|
||||
if err != nil {
|
||||
log.Ctx(ctx).Error().Err(err).Send()
|
||||
continue
|
||||
}
|
||||
cert.Certificate.KeyFile = types.FileOrContent(string(content))
|
||||
|
||||
certs = append(certs, cert)
|
||||
}
|
||||
|
||||
return certs
|
||||
}
|
||||
|
||||
func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory string, configuration *dynamic.Configuration) (*dynamic.Configuration, error) {
|
||||
fileList, err := os.ReadDir(directory)
|
||||
if err != nil {
|
||||
@@ -539,53 +555,6 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st
|
||||
return configuration, nil
|
||||
}
|
||||
|
||||
// CreateConfiguration creates a provider configuration from content using templating.
|
||||
func (p *Provider) CreateConfiguration(ctx context.Context, filename string, funcMap template.FuncMap, templateObjects interface{}) (*dynamic.Configuration, error) {
|
||||
tmplContent, err := readFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading configuration file: %s - %w", filename, err)
|
||||
}
|
||||
|
||||
defaultFuncMap := sprig.TxtFuncMap()
|
||||
defaultFuncMap["normalize"] = provider.Normalize
|
||||
defaultFuncMap["split"] = strings.Split
|
||||
for funcID, funcElement := range funcMap {
|
||||
defaultFuncMap[funcID] = funcElement
|
||||
}
|
||||
|
||||
tmpl := template.New(p.Filename).Funcs(defaultFuncMap)
|
||||
|
||||
_, err = tmpl.Parse(tmplContent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var buffer bytes.Buffer
|
||||
err = tmpl.Execute(&buffer, templateObjects)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
renderedTemplate := buffer.String()
|
||||
if p.DebugLogGeneratedTemplate {
|
||||
logger := log.Ctx(ctx)
|
||||
logger.Debug().Msgf("Template content: %s", tmplContent)
|
||||
logger.Debug().Msgf("Rendering results: %s", renderedTemplate)
|
||||
}
|
||||
|
||||
return p.decodeConfiguration(filename, renderedTemplate)
|
||||
}
|
||||
|
||||
// DecodeConfiguration Decodes a *types.Configuration from a content.
|
||||
func (p *Provider) DecodeConfiguration(filename string) (*dynamic.Configuration, error) {
|
||||
content, err := readFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading configuration file: %s - %w", filename, err)
|
||||
}
|
||||
|
||||
return p.decodeConfiguration(filename, content)
|
||||
}
|
||||
|
||||
func (p *Provider) decodeConfiguration(filePath, content string) (*dynamic.Configuration, error) {
|
||||
configuration := &dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
@@ -618,6 +587,36 @@ func (p *Provider) decodeConfiguration(filePath, content string) (*dynamic.Confi
|
||||
return configuration, nil
|
||||
}
|
||||
|
||||
func sendConfigToChannel(configurationChan chan<- dynamic.Message, configuration *dynamic.Configuration) {
|
||||
configurationChan <- dynamic.Message{
|
||||
ProviderName: "file",
|
||||
Configuration: configuration,
|
||||
}
|
||||
}
|
||||
|
||||
func flattenCertificates(ctx context.Context, tlsConfig *dynamic.TLSConfiguration) []*tls.CertAndStores {
|
||||
var certs []*tls.CertAndStores
|
||||
for _, cert := range tlsConfig.Certificates {
|
||||
content, err := cert.Certificate.CertFile.Read()
|
||||
if err != nil {
|
||||
log.Ctx(ctx).Error().Err(err).Send()
|
||||
continue
|
||||
}
|
||||
cert.Certificate.CertFile = types.FileOrContent(string(content))
|
||||
|
||||
content, err = cert.Certificate.KeyFile.Read()
|
||||
if err != nil {
|
||||
log.Ctx(ctx).Error().Err(err).Send()
|
||||
continue
|
||||
}
|
||||
cert.Certificate.KeyFile = types.FileOrContent(string(content))
|
||||
|
||||
certs = append(certs, cert)
|
||||
}
|
||||
|
||||
return certs
|
||||
}
|
||||
|
||||
func readFile(filename string) (string, error) {
|
||||
if len(filename) > 0 {
|
||||
buf, err := os.ReadFile(filename)
|
||||
|
||||
@@ -34,7 +34,7 @@ const resyncPeriod = 10 * time.Minute
|
||||
// WatchAll starts the watch of the Provider resources and updates the stores.
|
||||
// The stores can then be accessed via the Get* functions.
|
||||
type Client interface {
|
||||
WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error)
|
||||
WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan any, error)
|
||||
GetIngressRoutes() []*traefikv1alpha1.IngressRoute
|
||||
GetIngressRouteTCPs() []*traefikv1alpha1.IngressRouteTCP
|
||||
GetIngressRouteUDPs() []*traefikv1alpha1.IngressRouteUDP
|
||||
@@ -157,8 +157,8 @@ func newExternalClusterClient(endpoint, caFilePath string, token types.FileOrCon
|
||||
}
|
||||
|
||||
// WatchAll starts namespace-specific controllers for all relevant kinds.
|
||||
func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error) {
|
||||
eventCh := make(chan interface{}, 1)
|
||||
func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan any, error) {
|
||||
eventCh := make(chan any, 1)
|
||||
eventHandler := &k8s.ResourceEventHandler{Ev: eventCh}
|
||||
|
||||
if len(namespaces) == 0 {
|
||||
|
||||
@@ -29,8 +29,8 @@ func TestClientIgnoresHelmOwnedSecrets(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
kubeClient := kubefake.NewSimpleClientset(helmSecret, secret)
|
||||
crdClient := traefikcrdfake.NewSimpleClientset()
|
||||
kubeClient := kubefake.NewClientset(helmSecret, secret)
|
||||
crdClient := traefikcrdfake.NewClientset()
|
||||
|
||||
client := newClientImpl(kubeClient, crdClient)
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
sync "sync"
|
||||
|
||||
typed "sigs.k8s.io/structured-merge-diff/v6/typed"
|
||||
)
|
||||
|
||||
func Parser() *typed.Parser {
|
||||
parserOnce.Do(func() {
|
||||
var err error
|
||||
parser, err = typed.NewParser(schemaYAML)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to parse schema: %v", err))
|
||||
}
|
||||
})
|
||||
return parser
|
||||
}
|
||||
|
||||
var parserOnce sync.Once
|
||||
var parser *typed.Parser
|
||||
var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: __untyped_atomic_
|
||||
scalar: untyped
|
||||
list:
|
||||
elementType:
|
||||
namedType: __untyped_atomic_
|
||||
elementRelationship: atomic
|
||||
map:
|
||||
elementType:
|
||||
namedType: __untyped_atomic_
|
||||
elementRelationship: atomic
|
||||
- name: __untyped_deduced_
|
||||
scalar: untyped
|
||||
list:
|
||||
elementType:
|
||||
namedType: __untyped_atomic_
|
||||
elementRelationship: atomic
|
||||
map:
|
||||
elementType:
|
||||
namedType: __untyped_deduced_
|
||||
elementRelationship: separable
|
||||
`)
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
// BasicAuthApplyConfiguration represents a declarative configuration of the BasicAuth type for use
|
||||
// with apply.
|
||||
type BasicAuthApplyConfiguration struct {
|
||||
Secret *string `json:"secret,omitempty"`
|
||||
Realm *string `json:"realm,omitempty"`
|
||||
RemoveHeader *bool `json:"removeHeader,omitempty"`
|
||||
HeaderField *string `json:"headerField,omitempty"`
|
||||
}
|
||||
|
||||
// BasicAuthApplyConfiguration constructs a declarative configuration of the BasicAuth type for use with
|
||||
// apply.
|
||||
func BasicAuth() *BasicAuthApplyConfiguration {
|
||||
return &BasicAuthApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithSecret sets the Secret field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Secret field is set to the value of the last call.
|
||||
func (b *BasicAuthApplyConfiguration) WithSecret(value string) *BasicAuthApplyConfiguration {
|
||||
b.Secret = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithRealm sets the Realm field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Realm field is set to the value of the last call.
|
||||
func (b *BasicAuthApplyConfiguration) WithRealm(value string) *BasicAuthApplyConfiguration {
|
||||
b.Realm = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithRemoveHeader sets the RemoveHeader field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the RemoveHeader field is set to the value of the last call.
|
||||
func (b *BasicAuthApplyConfiguration) WithRemoveHeader(value bool) *BasicAuthApplyConfiguration {
|
||||
b.RemoveHeader = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithHeaderField sets the HeaderField field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the HeaderField field is set to the value of the last call.
|
||||
func (b *BasicAuthApplyConfiguration) WithHeaderField(value string) *BasicAuthApplyConfiguration {
|
||||
b.HeaderField = &value
|
||||
return b
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
// CertificateApplyConfiguration represents a declarative configuration of the Certificate type for use
|
||||
// with apply.
|
||||
type CertificateApplyConfiguration struct {
|
||||
SecretName *string `json:"secretName,omitempty"`
|
||||
}
|
||||
|
||||
// CertificateApplyConfiguration constructs a declarative configuration of the Certificate type for use with
|
||||
// apply.
|
||||
func Certificate() *CertificateApplyConfiguration {
|
||||
return &CertificateApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithSecretName sets the SecretName field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the SecretName field is set to the value of the last call.
|
||||
func (b *CertificateApplyConfiguration) WithSecretName(value string) *CertificateApplyConfiguration {
|
||||
b.SecretName = &value
|
||||
return b
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user