Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create init method on provider interface #3580

Merged
merged 9 commits into from
Jul 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 21 additions & 3 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@

[[constraint]]
name = "github.com/containous/traefik-extra-service-fabric"
version = "1.2.0"
branch = "init-provider"

[[constraint]]
name = "github.com/coreos/go-systemd"
Expand Down
6 changes: 5 additions & 1 deletion cmd/traefik/traefik.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,11 @@ func runCmd(globalConfiguration *configuration.GlobalConfiguration, configFile s

acmeprovider := globalConfiguration.InitACMEProvider()
if acmeprovider != nil {
providerAggregator.AddProvider(acmeprovider)
err := providerAggregator.AddProvider(acmeprovider)
if err != nil {
log.Errorf("Error initializing provider ACME: %v", err)
acmeprovider = nil
}
}

entryPoints := map[string]server.EntryPoint{}
Expand Down
70 changes: 44 additions & 26 deletions configuration/provider_aggregator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package configuration

import (
"encoding/json"
"reflect"

"github.com/containous/traefik/log"
"github.com/containous/traefik/provider"
Expand All @@ -12,82 +11,101 @@ import (

// ProviderAggregator aggregate providers
type ProviderAggregator struct {
providers []provider.Provider
providers []provider.Provider
constraints types.Constraints
}

// NewProviderAggregator return an aggregate of all the providers configured in GlobalConfiguration
func NewProviderAggregator(gc *GlobalConfiguration) ProviderAggregator {
provider := ProviderAggregator{}
provider := ProviderAggregator{
constraints: gc.Constraints,
}
if gc.Docker != nil {
provider.providers = append(provider.providers, gc.Docker)
provider.quietAddProvider(gc.Docker)
}
if gc.Marathon != nil {
provider.providers = append(provider.providers, gc.Marathon)
provider.quietAddProvider(gc.Marathon)
}
if gc.File != nil {
provider.providers = append(provider.providers, gc.File)
provider.quietAddProvider(gc.File)
}
if gc.Rest != nil {
provider.providers = append(provider.providers, gc.Rest)
provider.quietAddProvider(gc.Rest)
}
if gc.Consul != nil {
provider.providers = append(provider.providers, gc.Consul)
provider.quietAddProvider(gc.Consul)
}
if gc.ConsulCatalog != nil {
provider.providers = append(provider.providers, gc.ConsulCatalog)
provider.quietAddProvider(gc.ConsulCatalog)
}
if gc.Etcd != nil {
provider.providers = append(provider.providers, gc.Etcd)
provider.quietAddProvider(gc.Etcd)
}
if gc.Zookeeper != nil {
provider.providers = append(provider.providers, gc.Zookeeper)
provider.quietAddProvider(gc.Zookeeper)
}
if gc.Boltdb != nil {
provider.providers = append(provider.providers, gc.Boltdb)
provider.quietAddProvider(gc.Boltdb)
}
if gc.Kubernetes != nil {
provider.providers = append(provider.providers, gc.Kubernetes)
provider.quietAddProvider(gc.Kubernetes)
}
if gc.Mesos != nil {
provider.providers = append(provider.providers, gc.Mesos)
provider.quietAddProvider(gc.Mesos)
}
if gc.Eureka != nil {
provider.providers = append(provider.providers, gc.Eureka)
provider.quietAddProvider(gc.Eureka)
}
if gc.ECS != nil {
provider.providers = append(provider.providers, gc.ECS)
provider.quietAddProvider(gc.ECS)
}
if gc.Rancher != nil {
provider.providers = append(provider.providers, gc.Rancher)
provider.quietAddProvider(gc.Rancher)
}
if gc.DynamoDB != nil {
provider.providers = append(provider.providers, gc.DynamoDB)
provider.quietAddProvider(gc.DynamoDB)
}
if gc.ServiceFabric != nil {
provider.providers = append(provider.providers, gc.ServiceFabric)
provider.quietAddProvider(gc.ServiceFabric)
}
return provider
}

func (p *ProviderAggregator) quietAddProvider(provider provider.Provider) {
err := p.AddProvider(provider)
if err != nil {
log.Errorf("Error initializing provider %T: %v", provider, err)
}
}

// AddProvider add a provider in the providers map
func (p *ProviderAggregator) AddProvider(provider provider.Provider) {
func (p *ProviderAggregator) AddProvider(provider provider.Provider) error {
err := provider.Init(p.constraints)
if err != nil {
return err
}
p.providers = append(p.providers, provider)
return nil
}

// Init the provider
func (p ProviderAggregator) Init(_ types.Constraints) error {
return nil
}

// Provide call the provide method of every providers
func (p ProviderAggregator) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
func (p ProviderAggregator) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool) 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.Debugf("Unable to marshal provider conf %T with error: %v", p, err)
}
log.Infof("Starting provider %v %s", providerType, jsonConf)
log.Infof("Starting provider %T %s", p, jsonConf)
currentProvider := p
safe.Go(func() {
err := currentProvider.Provide(configurationChan, pool, constraints)
err := currentProvider.Provide(configurationChan, pool)
if err != nil {
log.Errorf("Error starting provider %v: %s", providerType, err)
log.Errorf("Error starting provider %T: %v", p, err)
}
})
}
Expand Down
75 changes: 36 additions & 39 deletions provider/acme/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,45 @@ func (p *Provider) ListenRequest(domain string) (*tls.Certificate, error) {
return &certificate, err
}

// Init for compatibility reason the BaseProvider implements an empty Init
func (p *Provider) Init(_ types.Constraints) error {
acme.UserAgent = fmt.Sprintf("containous-traefik/%s", version.Version)
if p.ACMELogging {
legolog.Logger = fmtlog.New(log.WriterLevel(logrus.InfoLevel), "legolog: ", 0)
} else {
legolog.Logger = fmtlog.New(ioutil.Discard, "", 0)
}

if p.Store == nil {
return errors.New("no store found for the ACME provider")
}

var err error
p.account, err = p.Store.GetAccount()
if err != nil {
return fmt.Errorf("unable to get ACME account : %v", err)
}

// Reset Account if caServer changed, thus registration URI can be updated
if p.account != nil && p.account.Registration != nil && !strings.HasPrefix(p.account.Registration.URI, p.CAServer) {
p.account = nil
}

p.certificates, err = p.Store.GetCertificates()
if err != nil {
return fmt.Errorf("unable to get ACME certificates : %v", err)
}

return nil
}

// Provide allows the file provider to provide configurations to traefik
// using the given Configuration channel.
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool) error {
p.pool = pool
err := p.init()
if err != nil {
return err
}

p.watchCertificate()
p.watchNewDomains()

p.configurationChan = configurationChan
p.refreshCertificates()
Expand Down Expand Up @@ -150,40 +181,6 @@ func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *s
return nil
}

func (p *Provider) init() error {
acme.UserAgent = fmt.Sprintf("containous-traefik/%s", version.Version)
if p.ACMELogging {
legolog.Logger = fmtlog.New(log.WriterLevel(logrus.InfoLevel), "legolog: ", 0)
} else {
legolog.Logger = fmtlog.New(ioutil.Discard, "", 0)
}

if p.Store == nil {
return errors.New("no store found for the ACME provider")
}

var err error
p.account, err = p.Store.GetAccount()
if err != nil {
return fmt.Errorf("unable to get ACME account : %v", err)
}

// Reset Account if caServer changed, thus registration URI can be updated
if p.account != nil && p.account.Registration != nil && !strings.HasPrefix(p.account.Registration.URI, p.CAServer) {
p.account = nil
}

p.certificates, err = p.Store.GetCertificates()
if err != nil {
return fmt.Errorf("unable to get ACME certificates : %v", err)
}

p.watchCertificate()
p.watchNewDomains()

return nil
}

func (p *Provider) getClient() (*acme.Client, error) {
p.clientMutex.Lock()
defer p.clientMutex.Unlock()
Expand Down
19 changes: 15 additions & 4 deletions provider/boltdb/boltdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,26 @@ type Provider struct {
kv.Provider `mapstructure:",squash" export:"true"`
}

// Provide allows the boltdb provider to Provide configurations to traefik
// using the given configuration channel.
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
// Init the provider
func (p *Provider) Init(constraints types.Constraints) error {
err := p.Provider.Init(constraints)
if err != nil {
return err
}

store, err := p.CreateStore()
if err != nil {
return fmt.Errorf("failed to Connect to KV store: %v", err)
}

p.SetKVClient(store)
return p.Provider.Provide(configurationChan, pool, constraints)
return nil
}

// Provide allows the boltdb provider to Provide configurations to traefik
// using the given configuration channel.
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool) error {
return p.Provider.Provide(configurationChan, pool)
}

// CreateStore creates the KV store
Expand Down
19 changes: 15 additions & 4 deletions provider/consul/consul.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,26 @@ type Provider struct {
kv.Provider `mapstructure:",squash" export:"true"`
}

// Provide allows the consul provider to provide configurations to traefik
// using the given configuration channel.
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
// Init the provider
func (p *Provider) Init(constraints types.Constraints) error {
err := p.Provider.Init(constraints)
if err != nil {
return err
}

store, err := p.CreateStore()
if err != nil {
return fmt.Errorf("failed to Connect to KV store: %v", err)
}

p.SetKVClient(store)
return p.Provider.Provide(configurationChan, pool, constraints)
return nil
}

// Provide allows the consul provider to provide configurations to traefik
// using the given configuration channel.
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool) error {
return p.Provider.Provide(configurationChan, pool)
}

// CreateStore creates the KV store
Expand Down