Add internal provider

Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
This commit is contained in:
Ludovic Fernandez 2019-11-14 16:40:05 +01:00 committed by Traefiker Bot
parent 2ee2e29262
commit 424e2a9439
71 changed files with 2523 additions and 1469 deletions

View file

@ -16,6 +16,7 @@ import (
"github.com/containous/traefik/v2/pkg/middlewares"
"github.com/containous/traefik/v2/pkg/middlewares/forwardedheaders"
"github.com/containous/traefik/v2/pkg/safe"
"github.com/containous/traefik/v2/pkg/server/router"
"github.com/containous/traefik/v2/pkg/tcp"
"github.com/sirupsen/logrus"
"golang.org/x/net/http2"
@ -50,11 +51,60 @@ func (h *httpForwarder) Accept() (net.Conn, error) {
// TCPEntryPoints holds a map of TCPEntryPoint (the entrypoint names being the keys)
type TCPEntryPoints map[string]*TCPEntryPoint
// NewTCPEntryPoints creates a new TCPEntryPoints.
func NewTCPEntryPoints(staticConfiguration static.Configuration) (TCPEntryPoints, error) {
serverEntryPointsTCP := make(TCPEntryPoints)
for entryPointName, config := range staticConfiguration.EntryPoints {
ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName))
var err error
serverEntryPointsTCP[entryPointName], err = NewTCPEntryPoint(ctx, config)
if err != nil {
return nil, fmt.Errorf("error while building entryPoint %s: %v", entryPointName, err)
}
}
return serverEntryPointsTCP, nil
}
// Start the server entry points.
func (eps TCPEntryPoints) Start() {
for entryPointName, serverEntryPoint := range eps {
ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName))
go serverEntryPoint.StartTCP(ctx)
}
}
// Stop the server entry points.
func (eps TCPEntryPoints) Stop() {
var wg sync.WaitGroup
for epn, ep := range eps {
wg.Add(1)
go func(entryPointName string, entryPoint *TCPEntryPoint) {
defer wg.Done()
ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName))
entryPoint.Shutdown(ctx)
log.FromContext(ctx).Debugf("Entry point %s closed", entryPointName)
}(epn, ep)
}
wg.Wait()
}
// Switch the TCP routers.
func (eps TCPEntryPoints) Switch(routersTCP map[string]*tcp.Router) {
for entryPointName, rt := range routersTCP {
eps[entryPointName].SwitchRouter(rt)
}
}
// TCPEntryPoint is the TCP server
type TCPEntryPoint struct {
listener net.Listener
switcher *tcp.HandlerSwitcher
RouteAppenderFactory RouteAppenderFactory
transportConfiguration *static.EntryPointsTransport
tracker *connectionTracker
httpServer *httpServer
@ -99,35 +149,8 @@ func NewTCPEntryPoint(ctx context.Context, configuration *static.EntryPoint) (*T
}, nil
}
// writeCloserWrapper wraps together a connection, and the concrete underlying
// connection type that was found to satisfy WriteCloser.
type writeCloserWrapper struct {
net.Conn
writeCloser tcp.WriteCloser
}
func (c *writeCloserWrapper) CloseWrite() error {
return c.writeCloser.CloseWrite()
}
// writeCloser returns the given connection, augmented with the WriteCloser
// implementation, if any was found within the underlying conn.
func writeCloser(conn net.Conn) (tcp.WriteCloser, error) {
switch typedConn := conn.(type) {
case *proxyprotocol.Conn:
underlying, err := writeCloser(typedConn.Conn)
if err != nil {
return nil, err
}
return &writeCloserWrapper{writeCloser: underlying, Conn: typedConn}, nil
case *net.TCPConn:
return typedConn, nil
default:
return nil, fmt.Errorf("unknown connection type %T", typedConn)
}
}
func (e *TCPEntryPoint) startTCP(ctx context.Context) {
// StartTCP starts the TCP server.
func (e *TCPEntryPoint) StartTCP(ctx context.Context) {
logger := log.FromContext(ctx)
logger.Debugf("Start TCP Server")
@ -213,22 +236,55 @@ func (e *TCPEntryPoint) Shutdown(ctx context.Context) {
cancel()
}
func (e *TCPEntryPoint) switchRouter(router *tcp.Router) {
router.HTTPForwarder(e.httpServer.Forwarder)
router.HTTPSForwarder(e.httpsServer.Forwarder)
// SwitchRouter switches the TCP router handler.
func (e *TCPEntryPoint) SwitchRouter(rt *tcp.Router) {
rt.HTTPForwarder(e.httpServer.Forwarder)
httpHandler := router.GetHTTPHandler()
httpsHandler := router.GetHTTPSHandler()
httpHandler := rt.GetHTTPHandler()
if httpHandler == nil {
httpHandler = buildDefaultHTTPRouter()
}
if httpsHandler == nil {
httpsHandler = buildDefaultHTTPRouter()
httpHandler = router.BuildDefaultHTTPRouter()
}
e.httpServer.Switcher.UpdateHandler(httpHandler)
rt.HTTPSForwarder(e.httpsServer.Forwarder)
httpsHandler := rt.GetHTTPSHandler()
if httpsHandler == nil {
httpsHandler = router.BuildDefaultHTTPRouter()
}
e.httpsServer.Switcher.UpdateHandler(httpsHandler)
e.switcher.Switch(router)
e.switcher.Switch(rt)
}
// writeCloserWrapper wraps together a connection, and the concrete underlying
// connection type that was found to satisfy WriteCloser.
type writeCloserWrapper struct {
net.Conn
writeCloser tcp.WriteCloser
}
func (c *writeCloserWrapper) CloseWrite() error {
return c.writeCloser.CloseWrite()
}
// writeCloser returns the given connection, augmented with the WriteCloser
// implementation, if any was found within the underlying conn.
func writeCloser(conn net.Conn) (tcp.WriteCloser, error) {
switch typedConn := conn.(type) {
case *proxyprotocol.Conn:
underlying, err := writeCloser(typedConn.Conn)
if err != nil {
return nil, err
}
return &writeCloserWrapper{writeCloser: underlying, Conn: typedConn}, nil
case *net.TCPConn:
return typedConn, nil
default:
return nil, fmt.Errorf("unknown connection type %T", typedConn)
}
}
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
@ -382,7 +438,7 @@ type httpServer struct {
}
func createHTTPServer(ctx context.Context, ln net.Listener, configuration *static.EntryPoint, withH2c bool) (*httpServer, error) {
httpSwitcher := middlewares.NewHandlerSwitcher(buildDefaultHTTPRouter())
httpSwitcher := middlewares.NewHandlerSwitcher(router.BuildDefaultHTTPRouter())
var handler http.Handler
var err error