traefik/pkg/server/routerfactory.go
2024-09-16 16:41:57 +02:00

125 lines
4 KiB
Go

package server
import (
"context"
"github.com/rs/zerolog/log"
"github.com/traefik/traefik/v3/pkg/config/runtime"
"github.com/traefik/traefik/v3/pkg/config/static"
"github.com/traefik/traefik/v3/pkg/server/middleware"
tcpmiddleware "github.com/traefik/traefik/v3/pkg/server/middleware/tcp"
"github.com/traefik/traefik/v3/pkg/server/router"
tcprouter "github.com/traefik/traefik/v3/pkg/server/router/tcp"
udprouter "github.com/traefik/traefik/v3/pkg/server/router/udp"
"github.com/traefik/traefik/v3/pkg/server/service"
tcpsvc "github.com/traefik/traefik/v3/pkg/server/service/tcp"
udpsvc "github.com/traefik/traefik/v3/pkg/server/service/udp"
"github.com/traefik/traefik/v3/pkg/tcp"
"github.com/traefik/traefik/v3/pkg/tls"
"github.com/traefik/traefik/v3/pkg/udp"
)
// RouterFactory the factory of TCP/UDP routers.
type RouterFactory struct {
entryPointsTCP []string
entryPointsUDP []string
allowACMEByPass map[string]bool
managerFactory *service.ManagerFactory
pluginBuilder middleware.PluginsBuilder
observabilityMgr *middleware.ObservabilityMgr
tlsManager *tls.Manager
dialerManager *tcp.DialerManager
cancelPrevState func()
}
// NewRouterFactory creates a new RouterFactory.
func NewRouterFactory(staticConfiguration static.Configuration, managerFactory *service.ManagerFactory, tlsManager *tls.Manager,
observabilityMgr *middleware.ObservabilityMgr, pluginBuilder middleware.PluginsBuilder, dialerManager *tcp.DialerManager,
) *RouterFactory {
handlesTLSChallenge := false
for _, resolver := range staticConfiguration.CertificatesResolvers {
if resolver.ACME.TLSChallenge != nil {
handlesTLSChallenge = true
break
}
}
allowACMEByPass := map[string]bool{}
var entryPointsTCP, entryPointsUDP []string
for name, ep := range staticConfiguration.EntryPoints {
allowACMEByPass[name] = ep.AllowACMEByPass || !handlesTLSChallenge
protocol, err := ep.GetProtocol()
if err != nil {
// Should never happen because Traefik should not start if protocol is invalid.
log.Error().Err(err).Msg("Invalid protocol")
}
if protocol == "udp" {
entryPointsUDP = append(entryPointsUDP, name)
} else {
entryPointsTCP = append(entryPointsTCP, name)
}
}
return &RouterFactory{
entryPointsTCP: entryPointsTCP,
entryPointsUDP: entryPointsUDP,
managerFactory: managerFactory,
observabilityMgr: observabilityMgr,
tlsManager: tlsManager,
pluginBuilder: pluginBuilder,
dialerManager: dialerManager,
allowACMEByPass: allowACMEByPass,
}
}
// CreateRouters creates new TCPRouters and UDPRouters.
func (f *RouterFactory) CreateRouters(rtConf *runtime.Configuration) (map[string]*tcprouter.Router, map[string]udp.Handler) {
if f.cancelPrevState != nil {
f.cancelPrevState()
}
var ctx context.Context
ctx, f.cancelPrevState = context.WithCancel(context.Background())
// HTTP
serviceManager := f.managerFactory.Build(rtConf)
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, f.pluginBuilder)
routerManager := router.NewManager(rtConf, serviceManager, middlewaresBuilder, f.observabilityMgr, f.tlsManager)
handlersNonTLS := routerManager.BuildHandlers(ctx, f.entryPointsTCP, false)
handlersTLS := routerManager.BuildHandlers(ctx, f.entryPointsTCP, true)
serviceManager.LaunchHealthCheck(ctx)
// TCP
svcTCPManager := tcpsvc.NewManager(rtConf, f.dialerManager)
middlewaresTCPBuilder := tcpmiddleware.NewBuilder(rtConf.TCPMiddlewares)
rtTCPManager := tcprouter.NewManager(rtConf, svcTCPManager, middlewaresTCPBuilder, handlersNonTLS, handlersTLS, f.tlsManager)
routersTCP := rtTCPManager.BuildHandlers(ctx, f.entryPointsTCP)
for ep, r := range routersTCP {
if allowACMEByPass, ok := f.allowACMEByPass[ep]; ok && allowACMEByPass {
r.EnableACMETLSPassthrough()
}
}
// UDP
svcUDPManager := udpsvc.NewManager(rtConf)
rtUDPManager := udprouter.NewManager(rtConf, svcUDPManager)
routersUDP := rtUDPManager.BuildHandlers(ctx, f.entryPointsUDP)
rtConf.PopulateUsedBy()
return routersTCP, routersUDP
}