2019-03-14 08:30:04 +00:00
|
|
|
package tcp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/tls"
|
2019-05-16 08:58:06 +00:00
|
|
|
"fmt"
|
2019-03-14 08:30:04 +00:00
|
|
|
"net/http"
|
|
|
|
|
2019-03-15 08:42:03 +00:00
|
|
|
"github.com/containous/traefik/pkg/config"
|
|
|
|
"github.com/containous/traefik/pkg/log"
|
|
|
|
"github.com/containous/traefik/pkg/rules"
|
|
|
|
"github.com/containous/traefik/pkg/server/internal"
|
|
|
|
tcpservice "github.com/containous/traefik/pkg/server/service/tcp"
|
|
|
|
"github.com/containous/traefik/pkg/tcp"
|
2019-03-14 08:30:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// NewManager Creates a new Manager
|
2019-05-16 08:58:06 +00:00
|
|
|
func NewManager(conf *config.RuntimeConfiguration,
|
2019-03-14 08:30:04 +00:00
|
|
|
serviceManager *tcpservice.Manager,
|
|
|
|
httpHandlers map[string]http.Handler,
|
|
|
|
httpsHandlers map[string]http.Handler,
|
|
|
|
tlsConfig *tls.Config,
|
|
|
|
) *Manager {
|
|
|
|
return &Manager{
|
2019-05-16 08:58:06 +00:00
|
|
|
configs: conf.TCPRouters,
|
2019-03-14 08:30:04 +00:00
|
|
|
serviceManager: serviceManager,
|
|
|
|
httpHandlers: httpHandlers,
|
|
|
|
httpsHandlers: httpsHandlers,
|
|
|
|
tlsConfig: tlsConfig,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Manager is a route/router manager
|
|
|
|
type Manager struct {
|
2019-05-16 08:58:06 +00:00
|
|
|
configs map[string]*config.TCPRouterInfo
|
2019-03-14 08:30:04 +00:00
|
|
|
serviceManager *tcpservice.Manager
|
|
|
|
httpHandlers map[string]http.Handler
|
|
|
|
httpsHandlers map[string]http.Handler
|
|
|
|
tlsConfig *tls.Config
|
|
|
|
}
|
|
|
|
|
|
|
|
// BuildHandlers builds the handlers for the given entrypoints
|
|
|
|
func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string) map[string]*tcp.Router {
|
|
|
|
entryPointsRouters := m.filteredRouters(rootCtx, entryPoints)
|
|
|
|
|
|
|
|
entryPointHandlers := make(map[string]*tcp.Router)
|
|
|
|
for _, entryPointName := range entryPoints {
|
|
|
|
entryPointName := entryPointName
|
|
|
|
|
|
|
|
routers := entryPointsRouters[entryPointName]
|
|
|
|
|
|
|
|
ctx := log.With(rootCtx, log.Str(log.EntryPointName, entryPointName))
|
|
|
|
|
|
|
|
handler, err := m.buildEntryPointHandler(ctx, routers, m.httpHandlers[entryPointName], m.httpsHandlers[entryPointName])
|
|
|
|
if err != nil {
|
|
|
|
log.FromContext(ctx).Error(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
entryPointHandlers[entryPointName] = handler
|
|
|
|
}
|
|
|
|
return entryPointHandlers
|
|
|
|
}
|
|
|
|
|
2019-05-16 08:58:06 +00:00
|
|
|
func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string]*config.TCPRouterInfo, handlerHTTP http.Handler, handlerHTTPS http.Handler) (*tcp.Router, error) {
|
2019-03-14 08:30:04 +00:00
|
|
|
router := &tcp.Router{}
|
|
|
|
router.HTTPHandler(handlerHTTP)
|
|
|
|
router.HTTPSHandler(handlerHTTPS, m.tlsConfig)
|
2019-05-09 12:30:06 +00:00
|
|
|
|
2019-03-14 08:30:04 +00:00
|
|
|
for routerName, routerConfig := range configs {
|
2019-05-09 12:30:06 +00:00
|
|
|
ctxRouter := log.With(internal.AddProviderInContext(ctx, routerName), log.Str(log.RouterName, routerName))
|
2019-03-14 08:30:04 +00:00
|
|
|
logger := log.FromContext(ctxRouter)
|
|
|
|
|
|
|
|
handler, err := m.serviceManager.BuildTCP(ctxRouter, routerConfig.Service)
|
|
|
|
if err != nil {
|
2019-05-16 08:58:06 +00:00
|
|
|
routerConfig.Err = err.Error()
|
2019-03-14 08:30:04 +00:00
|
|
|
logger.Error(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
domains, err := rules.ParseHostSNI(routerConfig.Rule)
|
|
|
|
if err != nil {
|
2019-05-16 08:58:06 +00:00
|
|
|
routerErr := fmt.Errorf("unknown rule %s", routerConfig.Rule)
|
|
|
|
routerConfig.Err = routerErr.Error()
|
|
|
|
logger.Debug(routerErr)
|
2019-03-14 08:30:04 +00:00
|
|
|
continue
|
|
|
|
}
|
2019-05-09 12:30:06 +00:00
|
|
|
|
2019-03-14 08:30:04 +00:00
|
|
|
for _, domain := range domains {
|
2019-05-16 08:58:06 +00:00
|
|
|
logger.Debugf("Adding route %s on TCP", domain)
|
2019-03-14 08:30:04 +00:00
|
|
|
switch {
|
|
|
|
case routerConfig.TLS != nil:
|
|
|
|
if routerConfig.TLS.Passthrough {
|
|
|
|
router.AddRoute(domain, handler)
|
|
|
|
} else {
|
|
|
|
router.AddRouteTLS(domain, handler, m.tlsConfig)
|
|
|
|
}
|
|
|
|
case domain == "*":
|
|
|
|
router.AddCatchAllNoTLS(handler)
|
|
|
|
default:
|
|
|
|
logger.Warn("TCP Router ignored, cannot specify a Host rule without TLS")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return router, nil
|
|
|
|
}
|
|
|
|
|
2019-05-16 08:58:06 +00:00
|
|
|
func contains(entryPoints []string, entryPointName string) bool {
|
|
|
|
for _, name := range entryPoints {
|
|
|
|
if name == entryPointName {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Manager) filteredRouters(ctx context.Context, entryPoints []string) map[string]map[string]*config.TCPRouterInfo {
|
|
|
|
entryPointsRouters := make(map[string]map[string]*config.TCPRouterInfo)
|
2019-03-14 08:30:04 +00:00
|
|
|
|
|
|
|
for rtName, rt := range m.configs {
|
|
|
|
eps := rt.EntryPoints
|
|
|
|
if len(eps) == 0 {
|
|
|
|
eps = entryPoints
|
|
|
|
}
|
2019-05-09 12:30:06 +00:00
|
|
|
|
2019-03-14 08:30:04 +00:00
|
|
|
for _, entryPointName := range eps {
|
|
|
|
if !contains(entryPoints, entryPointName) {
|
|
|
|
log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))).
|
|
|
|
Errorf("entryPoint %q doesn't exist", entryPointName)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := entryPointsRouters[entryPointName]; !ok {
|
2019-05-16 08:58:06 +00:00
|
|
|
entryPointsRouters[entryPointName] = make(map[string]*config.TCPRouterInfo)
|
2019-03-14 08:30:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
entryPointsRouters[entryPointName][rtName] = rt
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return entryPointsRouters
|
|
|
|
}
|