From 395b1702dee610107e3690afef0490bc0beca282 Mon Sep 17 00:00:00 2001 From: SALLEYRON Julien Date: Mon, 29 Jan 2018 14:58:03 +0100 Subject: [PATCH] Extract providers configuration from server.go --- cmd/traefik/traefik.go | 2 +- configuration/provider_aggregator.go | 91 ++++++++++++++++++++++++++++ provider/rest/rest.go | 18 ++---- server/server.go | 87 ++++++-------------------- server/server_test.go | 12 ++-- 5 files changed, 121 insertions(+), 89 deletions(-) create mode 100644 configuration/provider_aggregator.go diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 72ef530e6..0a40eeef4 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -153,7 +153,7 @@ func run(globalConfiguration *configuration.GlobalConfiguration, configFile stri stats(globalConfiguration) log.Debugf("Global configuration loaded %s", string(jsonConf)) - svr := server.NewServer(*globalConfiguration) + svr := server.NewServer(*globalConfiguration, configuration.NewProviderAggregator(globalConfiguration)) svr.Start() defer svr.Close() diff --git a/configuration/provider_aggregator.go b/configuration/provider_aggregator.go new file mode 100644 index 000000000..198d2f502 --- /dev/null +++ b/configuration/provider_aggregator.go @@ -0,0 +1,91 @@ +package configuration + +import ( + "encoding/json" + "reflect" + + "github.com/containous/traefik/log" + "github.com/containous/traefik/provider" + "github.com/containous/traefik/safe" + "github.com/containous/traefik/types" +) + +type providerAggregator struct { + providers []provider.Provider +} + +// NewProviderAggregator return an aggregate of all the providers configured in GlobalConfiguration +func NewProviderAggregator(gc *GlobalConfiguration) provider.Provider { + provider := providerAggregator{} + if gc.Docker != nil { + provider.providers = append(provider.providers, gc.Docker) + } + if gc.Marathon != nil { + provider.providers = append(provider.providers, gc.Marathon) + } + if gc.File != nil { + provider.providers = append(provider.providers, gc.File) + } + if gc.Rest != nil { + provider.providers = append(provider.providers, gc.Rest) + } + if gc.Consul != nil { + provider.providers = append(provider.providers, gc.Consul) + } + if gc.ConsulCatalog != nil { + provider.providers = append(provider.providers, gc.ConsulCatalog) + } + if gc.Etcd != nil { + provider.providers = append(provider.providers, gc.Etcd) + } + if gc.Zookeeper != nil { + provider.providers = append(provider.providers, gc.Zookeeper) + } + if gc.Boltdb != nil { + provider.providers = append(provider.providers, gc.Boltdb) + } + if gc.Kubernetes != nil { + provider.providers = append(provider.providers, gc.Kubernetes) + } + if gc.Mesos != nil { + provider.providers = append(provider.providers, gc.Mesos) + } + if gc.Eureka != nil { + provider.providers = append(provider.providers, gc.Eureka) + } + if gc.ECS != nil { + provider.providers = append(provider.providers, gc.ECS) + } + if gc.Rancher != nil { + provider.providers = append(provider.providers, gc.Rancher) + } + if gc.DynamoDB != nil { + provider.providers = append(provider.providers, gc.DynamoDB) + } + if gc.ServiceFabric != nil { + provider.providers = append(provider.providers, gc.ServiceFabric) + } + if len(provider.providers) == 1 { + return provider.providers[0] + } + return provider +} + +func (p providerAggregator) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { + for _, p := range p.providers { + providerType := reflect.TypeOf(p) + jsonConf, err := json.Marshal(p) + if err != nil { + log.Debugf("Unable to marshal provider conf %v with error: %v", providerType, err) + } + log.Infof("Starting provider %v %s", providerType, jsonConf) + currentProvider := p + safe.Go(func() { + err := currentProvider.Provide(configurationChan, pool, constraints) + if err != nil { + log.Errorf("Error starting provider %v: %s", providerType, err) + } + }) + } + return nil +} diff --git a/provider/rest/rest.go b/provider/rest/rest.go index 4d9739d28..5041e874f 100644 --- a/provider/rest/rest.go +++ b/provider/rest/rest.go @@ -15,9 +15,8 @@ import ( // Provider is a provider.Provider implementation that provides a Rest API type Provider struct { - configurationChan chan<- types.ConfigMessage - EntryPoint string `description:"EntryPoint" export:"true"` - CurrentConfigurations *safe.Safe + configurationChan chan<- types.ConfigMessage + EntryPoint string `description:"EntryPoint" export:"true"` } var templatesRenderer = render.New(render.Options{Directory: "nowhere"}) @@ -45,7 +44,10 @@ func (p *Provider) AddRoutes(systemRouter *mux.Router) { if err == nil { // TODO: Deprecated configuration - Change to `rest` in the future p.configurationChan <- types.ConfigMessage{ProviderName: "web", Configuration: configuration} - p.getConfigHandler(response, request) + err := templatesRenderer.JSON(response, http.StatusOK, configuration) + if err != nil { + log.Error(err) + } } else { log.Errorf("Error parsing configuration %+v", err) http.Error(response, fmt.Sprintf("%+v", err), http.StatusBadRequest) @@ -59,11 +61,3 @@ func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *s p.configurationChan = configurationChan return nil } - -func (p *Provider) getConfigHandler(response http.ResponseWriter, request *http.Request) { - currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations) - err := templatesRenderer.JSON(response, http.StatusOK, currentConfigurations) - if err != nil { - log.Error(err) - } -} diff --git a/server/server.go b/server/server.go index b0be1d462..0f735d19a 100644 --- a/server/server.go +++ b/server/server.go @@ -65,7 +65,6 @@ type Server struct { configurationValidatedChan chan types.ConfigMessage signals chan os.Signal stopChan chan bool - providers []provider.Provider currentConfigurations safe.Safe providerConfigUpdateMap map[string]chan types.ConfigMessage globalConfiguration configuration.GlobalConfiguration @@ -75,6 +74,7 @@ type Server struct { leadership *cluster.Leadership defaultForwardingRoundTripper http.RoundTripper metricsRegistry metrics.Registry + provider provider.Provider } type serverEntryPoints map[string]*serverEntryPoint @@ -96,15 +96,15 @@ type serverRoute struct { } // NewServer returns an initialized Server. -func NewServer(globalConfiguration configuration.GlobalConfiguration) *Server { +func NewServer(globalConfiguration configuration.GlobalConfiguration, provider provider.Provider) *Server { server := new(Server) + server.provider = provider server.serverEntryPoints = make(map[string]*serverEntryPoint) server.configurationChan = make(chan types.ConfigMessage, 100) server.configurationValidatedChan = make(chan types.ConfigMessage, 100) server.signals = make(chan os.Signal, 1) server.stopChan = make(chan bool, 1) - server.providers = []provider.Provider{} server.configureSignals() currentConfigurations := make(types.Configurations) server.currentConfigurations.Set(currentConfigurations) @@ -207,8 +207,7 @@ func (s *Server) Start() { s.routinesPool.Go(func(stop chan bool) { s.listenConfigurations(stop) }) - s.configureProviders() - s.startProviders() + s.startProvider() go s.listenSignals() } @@ -541,73 +540,21 @@ func (s *Server) postLoadConfiguration() { } } -func (s *Server) configureProviders() { - // configure providers - if s.globalConfiguration.Docker != nil { - s.providers = append(s.providers, s.globalConfiguration.Docker) - } - if s.globalConfiguration.Marathon != nil { - s.providers = append(s.providers, s.globalConfiguration.Marathon) - } - if s.globalConfiguration.File != nil { - s.providers = append(s.providers, s.globalConfiguration.File) - } - if s.globalConfiguration.Rest != nil { - s.providers = append(s.providers, s.globalConfiguration.Rest) - s.globalConfiguration.Rest.CurrentConfigurations = &s.currentConfigurations - } - if s.globalConfiguration.Consul != nil { - s.providers = append(s.providers, s.globalConfiguration.Consul) - } - if s.globalConfiguration.ConsulCatalog != nil { - s.providers = append(s.providers, s.globalConfiguration.ConsulCatalog) - } - if s.globalConfiguration.Etcd != nil { - s.providers = append(s.providers, s.globalConfiguration.Etcd) - } - if s.globalConfiguration.Zookeeper != nil { - s.providers = append(s.providers, s.globalConfiguration.Zookeeper) - } - if s.globalConfiguration.Boltdb != nil { - s.providers = append(s.providers, s.globalConfiguration.Boltdb) - } - if s.globalConfiguration.Kubernetes != nil { - s.providers = append(s.providers, s.globalConfiguration.Kubernetes) - } - if s.globalConfiguration.Mesos != nil { - s.providers = append(s.providers, s.globalConfiguration.Mesos) - } - if s.globalConfiguration.Eureka != nil { - s.providers = append(s.providers, s.globalConfiguration.Eureka) - } - if s.globalConfiguration.ECS != nil { - s.providers = append(s.providers, s.globalConfiguration.ECS) - } - if s.globalConfiguration.Rancher != nil { - s.providers = append(s.providers, s.globalConfiguration.Rancher) - } - if s.globalConfiguration.DynamoDB != nil { - s.providers = append(s.providers, s.globalConfiguration.DynamoDB) - } - if s.globalConfiguration.ServiceFabric != nil { - s.providers = append(s.providers, s.globalConfiguration.ServiceFabric) - } -} - -func (s *Server) startProviders() { +func (s *Server) startProvider() { // start providers - for _, p := range s.providers { - providerType := reflect.TypeOf(p) - jsonConf, _ := json.Marshal(p) - log.Infof("Starting provider %v %s", providerType, jsonConf) - currentProvider := p - safe.Go(func() { - err := currentProvider.Provide(s.configurationChan, s.routinesPool, s.globalConfiguration.Constraints) - if err != nil { - log.Errorf("Error starting provider %v: %s", providerType, err) - } - }) + providerType := reflect.TypeOf(s.provider) + jsonConf, err := json.Marshal(s.provider) + if err != nil { + log.Debugf("Unable to marshal provider conf %v with error: %v", providerType, err) } + log.Infof("Starting provider %v %s", providerType, jsonConf) + currentProvider := s.provider + safe.Go(func() { + err := currentProvider.Provide(s.configurationChan, s.routinesPool, s.globalConfiguration.Constraints) + if err != nil { + log.Errorf("Error starting provider %v: %s", providerType, err) + } + }) } func createClientTLSConfig(entryPointName string, tlsOption *traefikTls.TLS) (*tls.Config, error) { diff --git a/server/server_test.go b/server/server_test.go index 02f19fe23..e6e52604b 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -141,7 +141,7 @@ func TestPrepareServerTimeouts(t *testing.T) { } router := middlewares.NewHandlerSwitcher(mux.NewRouter()) - srv := NewServer(test.globalConfig) + srv := NewServer(test.globalConfig, nil) httpServer, _, err := srv.prepareServer(entryPointName, entryPoint, router, nil, nil) if err != nil { t.Fatalf("Unexpected error when preparing srv: %s", err) @@ -282,7 +282,7 @@ func setupListenProvider(throttleDuration time.Duration) (server *Server, stop c ProvidersThrottleDuration: flaeg.Duration(throttleDuration), } - server = NewServer(globalConfig) + server = NewServer(globalConfig, nil) go server.listenProviders(stop) return server, stop, invokeStopChan @@ -475,7 +475,7 @@ func TestServerLoadConfigHealthCheckOptions(t *testing.T) { }, } - srv := NewServer(globalConfig) + srv := NewServer(globalConfig, nil) if _, err := srv.loadConfig(dynamicConfigs, globalConfig); err != nil { t.Fatalf("got error: %s", err) } @@ -647,7 +647,7 @@ func TestServerLoadConfigEmptyBasicAuth(t *testing.T) { }, } - srv := NewServer(globalConfig) + srv := NewServer(globalConfig, nil) if _, err := srv.loadConfig(dynamicConfigs, globalConfig); err != nil { t.Fatalf("got error: %s", err) } @@ -675,7 +675,7 @@ func TestServerLoadCertificateWithDefaultEntryPoint(t *testing.T) { }, } - srv := NewServer(globalConfig) + srv := NewServer(globalConfig, nil) if mapEntryPoints, err := srv.loadConfig(dynamicConfigs, globalConfig); err != nil { t.Fatalf("got error: %s", err) } else if mapEntryPoints["https"].certs.Get() == nil { @@ -905,7 +905,7 @@ func TestServerResponseEmptyBackend(t *testing.T) { } dynamicConfigs := types.Configurations{"config": test.dynamicConfig(testServer.URL)} - srv := NewServer(globalConfig) + srv := NewServer(globalConfig, nil) entryPoints, err := srv.loadConfig(dynamicConfigs, globalConfig) if err != nil { t.Fatalf("error loading config: %s", err)