2015-09-11 14:37:13 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2018-03-14 12:14:03 +00:00
|
|
|
"context"
|
2016-05-03 14:52:14 +00:00
|
|
|
"encoding/json"
|
2019-06-17 09:48:05 +00:00
|
|
|
stdlog "log"
|
2017-08-21 21:18:02 +00:00
|
|
|
"net/http"
|
2016-07-21 14:33:49 +00:00
|
|
|
"os"
|
2017-04-27 15:36:04 +00:00
|
|
|
"path/filepath"
|
2020-03-09 10:12:05 +00:00
|
|
|
"sort"
|
2016-07-21 14:33:49 +00:00
|
|
|
"strings"
|
2016-10-27 14:17:02 +00:00
|
|
|
"time"
|
2016-07-21 14:33:49 +00:00
|
|
|
|
2016-10-27 14:17:02 +00:00
|
|
|
"github.com/coreos/go-systemd/daemon"
|
2019-02-18 06:52:03 +00:00
|
|
|
assetfs "github.com/elazarl/go-bindata-assetfs"
|
2018-01-22 11:16:03 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2020-08-17 16:04:03 +00:00
|
|
|
"github.com/traefik/paerser/cli"
|
2020-09-16 13:46:04 +00:00
|
|
|
"github.com/traefik/traefik/v2/autogen/genstatic"
|
|
|
|
"github.com/traefik/traefik/v2/cmd"
|
|
|
|
"github.com/traefik/traefik/v2/cmd/healthcheck"
|
|
|
|
cmdVersion "github.com/traefik/traefik/v2/cmd/version"
|
|
|
|
tcli "github.com/traefik/traefik/v2/pkg/cli"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/collector"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/config/runtime"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/config/static"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/log"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/metrics"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/pilot"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/plugins"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/provider/acme"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/provider/aggregator"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/provider/traefik"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/safe"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/server"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/server/middleware"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/server/service"
|
|
|
|
traefiktls "github.com/traefik/traefik/v2/pkg/tls"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/types"
|
|
|
|
"github.com/traefik/traefik/v2/pkg/version"
|
2018-04-11 14:30:04 +00:00
|
|
|
"github.com/vulcand/oxy/roundrobin"
|
2015-09-11 23:55:10 +00:00
|
|
|
)
|
2015-09-11 14:37:13 +00:00
|
|
|
|
|
|
|
func main() {
|
2018-02-19 00:04:45 +00:00
|
|
|
// traefik config inits
|
2019-06-17 09:48:05 +00:00
|
|
|
tConfig := cmd.NewTraefikConfiguration()
|
|
|
|
|
2020-08-17 16:04:03 +00:00
|
|
|
loaders := []cli.ResourceLoader{&tcli.FileLoader{}, &tcli.FlagLoader{}, &tcli.EnvLoader{}}
|
2018-02-19 00:04:45 +00:00
|
|
|
|
2019-06-17 09:48:05 +00:00
|
|
|
cmdTraefik := &cli.Command{
|
2016-05-03 14:52:14 +00:00
|
|
|
Name: "traefik",
|
2019-04-05 10:44:03 +00:00
|
|
|
Description: `Traefik is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.
|
2016-05-03 14:52:14 +00:00
|
|
|
Complete documentation is available at https://traefik.io`,
|
2019-06-17 09:48:05 +00:00
|
|
|
Configuration: tConfig,
|
|
|
|
Resources: loaders,
|
|
|
|
Run: func(_ []string) error {
|
2019-07-15 08:22:03 +00:00
|
|
|
return runCmd(&tConfig.Configuration)
|
2016-05-03 14:52:14 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-06-17 09:48:05 +00:00
|
|
|
err := cmdTraefik.AddCommand(healthcheck.NewCmd(&tConfig.Configuration, loaders))
|
2016-07-29 15:36:53 +00:00
|
|
|
if err != nil {
|
2019-06-17 09:48:05 +00:00
|
|
|
stdlog.Println(err)
|
2018-02-19 00:05:39 +00:00
|
|
|
os.Exit(1)
|
2016-07-29 15:36:53 +00:00
|
|
|
}
|
|
|
|
|
2019-06-17 09:48:05 +00:00
|
|
|
err = cmdTraefik.AddCommand(cmdVersion.NewCmd())
|
2016-06-24 07:58:42 +00:00
|
|
|
if err != nil {
|
2019-06-17 09:48:05 +00:00
|
|
|
stdlog.Println(err)
|
2018-02-19 00:05:39 +00:00
|
|
|
os.Exit(1)
|
2016-06-24 07:58:42 +00:00
|
|
|
}
|
|
|
|
|
2019-06-17 09:48:05 +00:00
|
|
|
err = cli.Execute(cmdTraefik)
|
|
|
|
if err != nil {
|
|
|
|
stdlog.Println(err)
|
2019-12-09 14:14:06 +00:00
|
|
|
logrus.Exit(1)
|
2015-11-23 14:41:16 +00:00
|
|
|
}
|
2016-05-03 14:52:14 +00:00
|
|
|
|
2019-12-09 14:14:06 +00:00
|
|
|
logrus.Exit(0)
|
2015-09-11 14:37:13 +00:00
|
|
|
}
|
2016-05-03 14:52:14 +00:00
|
|
|
|
2019-07-15 08:22:03 +00:00
|
|
|
func runCmd(staticConfiguration *static.Configuration) error {
|
2018-11-27 16:42:04 +00:00
|
|
|
configureLogging(staticConfiguration)
|
2017-10-11 08:38:03 +00:00
|
|
|
|
2017-08-25 14:10:03 +00:00
|
|
|
http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment
|
2016-05-30 09:37:12 +00:00
|
|
|
|
2018-08-06 18:00:03 +00:00
|
|
|
if err := roundrobin.SetDefaultWeight(0); err != nil {
|
2019-11-14 15:40:05 +00:00
|
|
|
log.WithoutContext().Errorf("Could not set round robin default weight: %v", err)
|
2018-08-06 18:00:03 +00:00
|
|
|
}
|
2018-04-11 14:30:04 +00:00
|
|
|
|
2019-07-15 08:22:03 +00:00
|
|
|
staticConfiguration.SetEffectiveConfiguration()
|
2019-07-19 09:52:04 +00:00
|
|
|
if err := staticConfiguration.ValidateConfiguration(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-10-11 08:38:03 +00:00
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Infof("Traefik version %s built on %s", version.Version, version.BuildDate)
|
2018-10-01 17:18:03 +00:00
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
jsonConf, err := json.Marshal(staticConfiguration)
|
2018-10-01 17:18:03 +00:00
|
|
|
if err != nil {
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Errorf("Could not marshal static configuration: %v", err)
|
|
|
|
log.WithoutContext().Debugf("Static configuration loaded [struct] %#v", staticConfiguration)
|
2018-10-01 17:18:03 +00:00
|
|
|
} else {
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Debugf("Static configuration loaded %s", string(jsonConf))
|
2018-10-01 17:18:03 +00:00
|
|
|
}
|
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
if staticConfiguration.API != nil && staticConfiguration.API.Dashboard {
|
|
|
|
staticConfiguration.API.DashboardAssets = &assetfs.AssetFS{Asset: genstatic.Asset, AssetInfo: genstatic.AssetInfo, AssetDir: genstatic.AssetDir, Prefix: "static"}
|
2018-05-25 13:10:04 +00:00
|
|
|
}
|
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
if staticConfiguration.Global.CheckNewVersion {
|
2017-10-11 08:38:03 +00:00
|
|
|
checkNewVersion()
|
|
|
|
}
|
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
stats(staticConfiguration)
|
2017-11-25 12:36:03 +00:00
|
|
|
|
2019-11-14 15:40:05 +00:00
|
|
|
svr, err := setupServer(staticConfiguration)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2018-04-23 13:30:03 +00:00
|
|
|
}
|
|
|
|
|
2018-03-14 12:14:03 +00:00
|
|
|
ctx := cmd.ContextWithSignal(context.Background())
|
2018-04-23 13:30:03 +00:00
|
|
|
|
2020-04-20 16:36:34 +00:00
|
|
|
if staticConfiguration.Experimental != nil && staticConfiguration.Experimental.DevPlugin != nil {
|
|
|
|
var cancel context.CancelFunc
|
|
|
|
ctx, cancel = context.WithTimeout(ctx, 30*time.Minute)
|
|
|
|
defer cancel()
|
|
|
|
}
|
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
if staticConfiguration.Ping != nil {
|
|
|
|
staticConfiguration.Ping.WithContext(ctx)
|
2018-04-23 13:30:03 +00:00
|
|
|
}
|
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
svr.Start(ctx)
|
2017-10-11 08:38:03 +00:00
|
|
|
defer svr.Close()
|
2017-11-23 15:10:04 +00:00
|
|
|
|
2017-10-11 08:38:03 +00:00
|
|
|
sent, err := daemon.SdNotify(false, "READY=1")
|
|
|
|
if !sent && err != nil {
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Errorf("Failed to notify: %v", err)
|
2017-10-11 08:38:03 +00:00
|
|
|
}
|
2017-11-23 15:10:04 +00:00
|
|
|
|
2017-10-11 08:38:03 +00:00
|
|
|
t, err := daemon.SdWatchdogEnabled(false)
|
|
|
|
if err != nil {
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Errorf("Could not enable Watchdog: %v", err)
|
2017-10-11 08:38:03 +00:00
|
|
|
} else if t != 0 {
|
|
|
|
// Send a ping each half time given
|
2019-02-05 16:10:03 +00:00
|
|
|
t /= 2
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Infof("Watchdog activated with timer duration %s", t)
|
2017-10-11 08:38:03 +00:00
|
|
|
safe.Go(func() {
|
|
|
|
tick := time.Tick(t)
|
|
|
|
for range tick {
|
2019-06-17 09:48:05 +00:00
|
|
|
resp, errHealthCheck := healthcheck.Do(*staticConfiguration)
|
|
|
|
if resp != nil {
|
2019-11-14 15:40:05 +00:00
|
|
|
_ = resp.Body.Close()
|
2019-06-17 09:48:05 +00:00
|
|
|
}
|
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
if staticConfiguration.Ping == nil || errHealthCheck == nil {
|
2017-11-23 15:10:04 +00:00
|
|
|
if ok, _ := daemon.SdNotify(false, "WATCHDOG=1"); !ok {
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Error("Fail to tick watchdog")
|
2017-11-23 15:10:04 +00:00
|
|
|
}
|
|
|
|
} else {
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Error(errHealthCheck)
|
2017-10-11 08:38:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-11-23 15:10:04 +00:00
|
|
|
|
2017-10-11 08:38:03 +00:00
|
|
|
svr.Wait()
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Info("Shutting down")
|
2019-01-15 08:44:03 +00:00
|
|
|
return nil
|
2017-10-11 08:38:03 +00:00
|
|
|
}
|
|
|
|
|
2019-11-14 15:40:05 +00:00
|
|
|
func setupServer(staticConfiguration *static.Configuration) (*server.Server, error) {
|
|
|
|
providerAggregator := aggregator.NewProviderAggregator(*staticConfiguration.Providers)
|
|
|
|
|
|
|
|
// adds internal provider
|
|
|
|
err := providerAggregator.AddProvider(traefik.New(*staticConfiguration))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
tlsManager := traefiktls.NewManager()
|
|
|
|
|
|
|
|
acmeProviders := initACMEProvider(staticConfiguration, &providerAggregator, tlsManager)
|
|
|
|
|
2020-01-06 15:56:05 +00:00
|
|
|
serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints)
|
2019-11-14 15:40:05 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-02-11 00:26:04 +00:00
|
|
|
serverEntryPointsUDP, err := server.NewUDPEntryPoints(staticConfiguration.EntryPoints)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-11-14 15:40:05 +00:00
|
|
|
ctx := context.Background()
|
|
|
|
routinesPool := safe.NewPool(ctx)
|
|
|
|
|
2020-08-10 13:26:04 +00:00
|
|
|
metricRegistries := registerMetricClients(staticConfiguration.Metrics)
|
|
|
|
|
|
|
|
var aviator *pilot.Pilot
|
|
|
|
if isPilotEnabled(staticConfiguration) {
|
|
|
|
pilotRegistry := metrics.RegisterPilot()
|
|
|
|
|
2020-09-15 10:08:03 +00:00
|
|
|
aviator = pilot.New(staticConfiguration.Pilot.Token, pilotRegistry, routinesPool)
|
2020-08-10 13:26:04 +00:00
|
|
|
routinesPool.GoCtx(func(ctx context.Context) {
|
|
|
|
aviator.Tick(ctx)
|
|
|
|
})
|
|
|
|
|
|
|
|
metricRegistries = append(metricRegistries, pilotRegistry)
|
|
|
|
}
|
|
|
|
|
|
|
|
metricsRegistry := metrics.NewMultiRegistry(metricRegistries)
|
2019-11-14 15:40:05 +00:00
|
|
|
accessLog := setupAccessLog(staticConfiguration.AccessLog)
|
|
|
|
chainBuilder := middleware.NewChainBuilder(*staticConfiguration, metricsRegistry, accessLog)
|
|
|
|
managerFactory := service.NewManagerFactory(*staticConfiguration, routinesPool, metricsRegistry)
|
2020-04-20 16:36:34 +00:00
|
|
|
|
|
|
|
client, plgs, devPlugin, err := initPlugins(staticConfiguration)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
pluginBuilder, err := plugins.NewBuilder(client, plgs, devPlugin)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder)
|
2019-11-14 15:40:05 +00:00
|
|
|
|
2020-03-09 10:12:05 +00:00
|
|
|
var defaultEntryPoints []string
|
2020-03-05 11:46:05 +00:00
|
|
|
for name, cfg := range staticConfiguration.EntryPoints {
|
|
|
|
protocol, err := cfg.GetProtocol()
|
|
|
|
if err != nil {
|
|
|
|
// Should never happen because Traefik should not start if protocol is invalid.
|
|
|
|
log.WithoutContext().Errorf("Invalid protocol: %v", err)
|
|
|
|
}
|
|
|
|
|
2020-03-16 15:54:04 +00:00
|
|
|
if protocol != "udp" && name != static.DefaultInternalEntryPointName {
|
2020-03-09 10:12:05 +00:00
|
|
|
defaultEntryPoints = append(defaultEntryPoints, name)
|
2020-03-05 11:46:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-09 10:12:05 +00:00
|
|
|
sort.Strings(defaultEntryPoints)
|
|
|
|
|
2020-03-05 11:46:05 +00:00
|
|
|
watcher := server.NewConfigurationWatcher(
|
|
|
|
routinesPool,
|
|
|
|
providerAggregator,
|
|
|
|
time.Duration(staticConfiguration.Providers.ProvidersThrottleDuration),
|
2020-03-09 10:12:05 +00:00
|
|
|
defaultEntryPoints,
|
2020-03-05 11:46:05 +00:00
|
|
|
)
|
2019-11-14 15:40:05 +00:00
|
|
|
|
|
|
|
watcher.AddListener(func(conf dynamic.Configuration) {
|
|
|
|
ctx := context.Background()
|
|
|
|
tlsManager.UpdateConfigs(ctx, conf.TLS.Stores, conf.TLS.Options, conf.TLS.Certificates)
|
|
|
|
})
|
|
|
|
|
|
|
|
watcher.AddListener(func(_ dynamic.Configuration) {
|
|
|
|
metricsRegistry.ConfigReloadsCounter().Add(1)
|
|
|
|
metricsRegistry.LastConfigReloadSuccessGauge().Set(float64(time.Now().Unix()))
|
|
|
|
})
|
|
|
|
|
2020-05-04 09:40:46 +00:00
|
|
|
watcher.AddListener(switchRouter(routerFactory, acmeProviders, serverEntryPointsTCP, serverEntryPointsUDP, aviator))
|
2019-11-14 15:40:05 +00:00
|
|
|
|
|
|
|
watcher.AddListener(func(conf dynamic.Configuration) {
|
|
|
|
if metricsRegistry.IsEpEnabled() || metricsRegistry.IsSvcEnabled() {
|
|
|
|
var eps []string
|
|
|
|
for key := range serverEntryPointsTCP {
|
|
|
|
eps = append(eps, key)
|
|
|
|
}
|
|
|
|
|
|
|
|
metrics.OnConfigurationUpdate(conf, eps)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
resolverNames := map[string]struct{}{}
|
|
|
|
for _, p := range acmeProviders {
|
|
|
|
resolverNames[p.ResolverName] = struct{}{}
|
|
|
|
watcher.AddListener(p.ListenConfiguration)
|
|
|
|
}
|
|
|
|
|
|
|
|
watcher.AddListener(func(config dynamic.Configuration) {
|
|
|
|
for rtName, rt := range config.HTTP.Routers {
|
|
|
|
if rt.TLS == nil || rt.TLS.CertResolver == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := resolverNames[rt.TLS.CertResolver]; !ok {
|
|
|
|
log.WithoutContext().Errorf("the router %s uses a non-existent resolver: %s", rtName, rt.TLS.CertResolver)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2020-02-11 00:26:04 +00:00
|
|
|
return server.NewServer(routinesPool, serverEntryPointsTCP, serverEntryPointsUDP, watcher, chainBuilder, accessLog), nil
|
2019-11-14 15:40:05 +00:00
|
|
|
}
|
|
|
|
|
2020-05-04 09:40:46 +00:00
|
|
|
func switchRouter(routerFactory *server.RouterFactory, acmeProviders []*acme.Provider, serverEntryPointsTCP server.TCPEntryPoints, serverEntryPointsUDP server.UDPEntryPoints, aviator *pilot.Pilot) func(conf dynamic.Configuration) {
|
2019-11-14 15:40:05 +00:00
|
|
|
return func(conf dynamic.Configuration) {
|
2020-05-04 09:40:46 +00:00
|
|
|
rtConf := runtime.NewConfig(conf)
|
|
|
|
|
|
|
|
routers, udpRouters := routerFactory.CreateRouters(rtConf)
|
|
|
|
|
2019-11-14 15:40:05 +00:00
|
|
|
for entryPointName, rt := range routers {
|
|
|
|
for _, p := range acmeProviders {
|
|
|
|
if p != nil && p.HTTPChallenge != nil && p.HTTPChallenge.EntryPoint == entryPointName {
|
|
|
|
rt.HTTPHandler(p.CreateHandler(rt.GetHTTPHandler()))
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-04 09:40:46 +00:00
|
|
|
|
|
|
|
if aviator != nil {
|
|
|
|
aviator.SetRuntimeConfiguration(rtConf)
|
|
|
|
}
|
|
|
|
|
2019-11-14 15:40:05 +00:00
|
|
|
serverEntryPointsTCP.Switch(routers)
|
2020-02-11 00:26:04 +00:00
|
|
|
serverEntryPointsUDP.Switch(udpRouters)
|
2019-11-14 15:40:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-11 10:06:07 +00:00
|
|
|
// initACMEProvider creates an acme provider from the ACME part of globalConfiguration.
|
2019-07-19 09:52:04 +00:00
|
|
|
func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.ProviderAggregator, tlsManager *traefiktls.Manager) []*acme.Provider {
|
|
|
|
challengeStore := acme.NewLocalChallengeStore()
|
|
|
|
localStores := map[string]*acme.LocalStore{}
|
|
|
|
|
|
|
|
var resolvers []*acme.Provider
|
|
|
|
for name, resolver := range c.CertificatesResolvers {
|
|
|
|
if resolver.ACME != nil {
|
|
|
|
if localStores[resolver.ACME.Storage] == nil {
|
|
|
|
localStores[resolver.ACME.Storage] = acme.NewLocalStore(resolver.ACME.Storage)
|
|
|
|
}
|
|
|
|
|
|
|
|
p := &acme.Provider{
|
|
|
|
Configuration: resolver.ACME,
|
|
|
|
Store: localStores[resolver.ACME.Storage],
|
|
|
|
ChallengeStore: challengeStore,
|
|
|
|
ResolverName: name,
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := providerAggregator.AddProvider(p); err != nil {
|
2020-01-24 15:30:07 +00:00
|
|
|
log.WithoutContext().Errorf("The ACME resolver %q is skipped from the resolvers list because: %v", name, err)
|
2019-07-19 09:52:04 +00:00
|
|
|
continue
|
|
|
|
}
|
2020-01-24 15:30:07 +00:00
|
|
|
|
2019-07-19 09:52:04 +00:00
|
|
|
p.SetTLSManager(tlsManager)
|
2020-01-24 15:30:07 +00:00
|
|
|
|
2019-07-19 09:52:04 +00:00
|
|
|
if p.TLSChallenge != nil {
|
|
|
|
tlsManager.TLSAlpnGetter = p.GetTLSALPNCertificate
|
|
|
|
}
|
2020-01-24 15:30:07 +00:00
|
|
|
|
2019-07-19 09:52:04 +00:00
|
|
|
p.SetConfigListenerChan(make(chan dynamic.Configuration))
|
2020-01-24 15:30:07 +00:00
|
|
|
|
2019-07-19 09:52:04 +00:00
|
|
|
resolvers = append(resolvers, p)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return resolvers
|
|
|
|
}
|
|
|
|
|
2020-08-10 13:26:04 +00:00
|
|
|
func registerMetricClients(metricsConfig *types.Metrics) []metrics.Registry {
|
2019-11-14 15:40:05 +00:00
|
|
|
if metricsConfig == nil {
|
2020-08-10 13:26:04 +00:00
|
|
|
return nil
|
2019-11-14 15:40:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var registries []metrics.Registry
|
|
|
|
|
|
|
|
if metricsConfig.Prometheus != nil {
|
|
|
|
ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "prometheus"))
|
|
|
|
prometheusRegister := metrics.RegisterPrometheus(ctx, metricsConfig.Prometheus)
|
|
|
|
if prometheusRegister != nil {
|
|
|
|
registries = append(registries, prometheusRegister)
|
|
|
|
log.FromContext(ctx).Debug("Configured Prometheus metrics")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if metricsConfig.Datadog != nil {
|
|
|
|
ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "datadog"))
|
|
|
|
registries = append(registries, metrics.RegisterDatadog(ctx, metricsConfig.Datadog))
|
|
|
|
log.FromContext(ctx).Debugf("Configured Datadog metrics: pushing to %s once every %s",
|
|
|
|
metricsConfig.Datadog.Address, metricsConfig.Datadog.PushInterval)
|
|
|
|
}
|
|
|
|
|
|
|
|
if metricsConfig.StatsD != nil {
|
|
|
|
ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "statsd"))
|
|
|
|
registries = append(registries, metrics.RegisterStatsd(ctx, metricsConfig.StatsD))
|
|
|
|
log.FromContext(ctx).Debugf("Configured StatsD metrics: pushing to %s once every %s",
|
|
|
|
metricsConfig.StatsD.Address, metricsConfig.StatsD.PushInterval)
|
|
|
|
}
|
|
|
|
|
|
|
|
if metricsConfig.InfluxDB != nil {
|
|
|
|
ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "influxdb"))
|
|
|
|
registries = append(registries, metrics.RegisterInfluxDB(ctx, metricsConfig.InfluxDB))
|
|
|
|
log.FromContext(ctx).Debugf("Configured InfluxDB metrics: pushing to %s once every %s",
|
|
|
|
metricsConfig.InfluxDB.Address, metricsConfig.InfluxDB.PushInterval)
|
|
|
|
}
|
|
|
|
|
2020-08-10 13:26:04 +00:00
|
|
|
return registries
|
2019-11-14 15:40:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func setupAccessLog(conf *types.AccessLog) *accesslog.Handler {
|
|
|
|
if conf == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
accessLoggerMiddleware, err := accesslog.NewHandler(conf)
|
|
|
|
if err != nil {
|
|
|
|
log.WithoutContext().Warnf("Unable to create access logger : %v", err)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return accessLoggerMiddleware
|
|
|
|
}
|
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
func configureLogging(staticConfiguration *static.Configuration) {
|
2017-10-11 08:38:03 +00:00
|
|
|
// configure default log flags
|
2019-06-17 09:48:05 +00:00
|
|
|
stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags)
|
2017-10-11 08:38:03 +00:00
|
|
|
|
|
|
|
// configure log level
|
2018-03-21 13:42:07 +00:00
|
|
|
// an explicitly defined log level always has precedence. if none is
|
|
|
|
// given and debug mode is disabled, the default is ERROR, and DEBUG
|
|
|
|
// otherwise.
|
2019-06-19 16:34:04 +00:00
|
|
|
levelStr := "error"
|
|
|
|
if staticConfiguration.Log != nil && staticConfiguration.Log.Level != "" {
|
2019-04-16 13:30:09 +00:00
|
|
|
levelStr = strings.ToLower(staticConfiguration.Log.Level)
|
2018-11-27 16:42:04 +00:00
|
|
|
}
|
2019-06-19 16:34:04 +00:00
|
|
|
|
2018-03-21 13:42:07 +00:00
|
|
|
level, err := logrus.ParseLevel(levelStr)
|
2016-06-02 09:37:51 +00:00
|
|
|
if err != nil {
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Errorf("Error getting level: %v", err)
|
2016-06-02 09:37:51 +00:00
|
|
|
}
|
|
|
|
log.SetLevel(level)
|
2017-09-21 08:42:02 +00:00
|
|
|
|
2018-07-31 17:28:03 +00:00
|
|
|
var logFile string
|
2018-11-27 16:42:04 +00:00
|
|
|
if staticConfiguration.Log != nil && len(staticConfiguration.Log.FilePath) > 0 {
|
|
|
|
logFile = staticConfiguration.Log.FilePath
|
2017-09-21 08:42:02 +00:00
|
|
|
}
|
|
|
|
|
2017-10-11 08:38:03 +00:00
|
|
|
// configure log format
|
2017-09-21 08:42:02 +00:00
|
|
|
var formatter logrus.Formatter
|
2018-11-27 16:42:04 +00:00
|
|
|
if staticConfiguration.Log != nil && staticConfiguration.Log.Format == "json" {
|
2017-09-21 08:42:02 +00:00
|
|
|
formatter = &logrus.JSONFormatter{}
|
|
|
|
} else {
|
2018-02-19 00:04:45 +00:00
|
|
|
disableColors := len(logFile) > 0
|
2017-09-21 08:42:02 +00:00
|
|
|
formatter = &logrus.TextFormatter{DisableColors: disableColors, FullTimestamp: true, DisableSorting: true}
|
|
|
|
}
|
|
|
|
log.SetFormatter(formatter)
|
|
|
|
|
|
|
|
if len(logFile) > 0 {
|
|
|
|
dir := filepath.Dir(logFile)
|
2017-04-27 15:36:04 +00:00
|
|
|
|
2020-07-07 12:42:03 +00:00
|
|
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Errorf("Failed to create log path %s: %s", dir, err)
|
2017-04-27 15:36:04 +00:00
|
|
|
}
|
|
|
|
|
2017-09-21 08:42:02 +00:00
|
|
|
err = log.OpenFile(logFile)
|
2017-10-11 08:38:03 +00:00
|
|
|
logrus.RegisterExitHandler(func() {
|
2017-08-11 10:04:58 +00:00
|
|
|
if err := log.CloseFile(); err != nil {
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Errorf("Error while closing log: %v", err)
|
2016-05-03 14:52:14 +00:00
|
|
|
}
|
2017-10-11 08:38:03 +00:00
|
|
|
})
|
2016-05-03 14:52:14 +00:00
|
|
|
if err != nil {
|
2018-11-27 16:42:04 +00:00
|
|
|
log.WithoutContext().Errorf("Error while opening log file %s: %v", logFile, err)
|
2016-05-03 14:52:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-13 15:18:55 +00:00
|
|
|
|
2017-10-02 08:32:02 +00:00
|
|
|
func checkNewVersion() {
|
2017-11-25 12:36:03 +00:00
|
|
|
ticker := time.Tick(24 * time.Hour)
|
|
|
|
safe.Go(func() {
|
|
|
|
for time.Sleep(10 * time.Minute); ; <-ticker {
|
|
|
|
version.CheckNewVersion()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
func stats(staticConfiguration *static.Configuration) {
|
2019-09-16 15:26:06 +00:00
|
|
|
logger := log.WithoutContext()
|
2019-03-14 18:32:03 +00:00
|
|
|
|
2019-09-16 15:26:06 +00:00
|
|
|
if staticConfiguration.Global.SendAnonymousUsage {
|
|
|
|
logger.Info(`Stats collection is enabled.`)
|
|
|
|
logger.Info(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`)
|
|
|
|
logger.Info(`Help us improve Traefik by leaving this feature on :)`)
|
2020-02-17 10:04:04 +00:00
|
|
|
logger.Info(`More details on: https://docs.traefik.io/contributing/data-collection/`)
|
2018-11-27 16:42:04 +00:00
|
|
|
collect(staticConfiguration)
|
2017-11-25 12:36:03 +00:00
|
|
|
} else {
|
2019-09-16 15:26:06 +00:00
|
|
|
logger.Info(`
|
2017-11-25 12:36:03 +00:00
|
|
|
Stats collection is disabled.
|
|
|
|
Help us improve Traefik by turning this feature on :)
|
2020-02-17 10:04:04 +00:00
|
|
|
More details on: https://docs.traefik.io/contributing/data-collection/
|
2017-11-25 12:36:03 +00:00
|
|
|
`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
func collect(staticConfiguration *static.Configuration) {
|
2017-11-25 12:36:03 +00:00
|
|
|
ticker := time.Tick(24 * time.Hour)
|
2017-10-02 08:32:02 +00:00
|
|
|
safe.Go(func() {
|
2017-11-25 12:36:03 +00:00
|
|
|
for time.Sleep(10 * time.Minute); ; <-ticker {
|
2018-11-27 16:42:04 +00:00
|
|
|
if err := collector.Collect(staticConfiguration); err != nil {
|
|
|
|
log.WithoutContext().Debug(err)
|
2017-10-02 08:32:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|