From 9387235a04da24f4488810fbcfcc8dada8426dc8 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Sun, 1 Nov 2015 19:34:54 +0100 Subject: [PATCH 1/3] Linting middlewares package Signed-off-by: Vincent Demeester --- middlewares/cbreaker.go | 5 ++--- middlewares/logger.go | 6 ++---- middlewares/routes.go | 5 ++--- middlewares/websocket.go | 10 +++++----- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/middlewares/cbreaker.go b/middlewares/cbreaker.go index 6ed02b28e..7a059809b 100644 --- a/middlewares/cbreaker.go +++ b/middlewares/cbreaker.go @@ -1,6 +1,3 @@ -/* -Copyright -*/ package middlewares import ( @@ -9,10 +6,12 @@ import ( "github.com/mailgun/oxy/cbreaker" ) +// CircuitBreaker holds the oxy circuit breaker. type CircuitBreaker struct { circuitBreaker *cbreaker.CircuitBreaker } +// NewCircuitBreaker returns a new CircuitBreaker. func NewCircuitBreaker(next http.Handler, expression string, options ...cbreaker.CircuitBreakerOption) *CircuitBreaker { circuitBreaker, _ := cbreaker.New(next, expression, options...) return &CircuitBreaker{circuitBreaker} diff --git a/middlewares/logger.go b/middlewares/logger.go index 5c14ee863..f569cfcb5 100644 --- a/middlewares/logger.go +++ b/middlewares/logger.go @@ -1,6 +1,3 @@ -/* -Copyright -*/ package middlewares import ( @@ -16,7 +13,7 @@ type Logger struct { file *os.File } -// NewLogger returns a new Logger instance +// NewLogger returns a new Logger instance. func NewLogger(file string) *Logger { if len(file) > 0 { fi, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) @@ -36,6 +33,7 @@ func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.Ha } } +// Close closes the logger (i.e. the file). func (l *Logger) Close() { l.file.Close() } diff --git a/middlewares/routes.go b/middlewares/routes.go index fa71e8d9e..991d3085d 100644 --- a/middlewares/routes.go +++ b/middlewares/routes.go @@ -1,6 +1,3 @@ -/* -Copyright -*/ package middlewares import ( @@ -11,10 +8,12 @@ import ( "github.com/gorilla/mux" ) +// Routes holds the gorilla mux routes (for the API & co). type Routes struct { router *mux.Router } +// NewRoutes return a Routes based on the given router. func NewRoutes(router *mux.Router) *Routes { return &Routes{router} } diff --git a/middlewares/websocket.go b/middlewares/websocket.go index ac7d6a035..6dfff2f01 100644 --- a/middlewares/websocket.go +++ b/middlewares/websocket.go @@ -1,20 +1,20 @@ -/* -Copyright -*/ package middlewares import ( - log "github.com/Sirupsen/logrus" - "github.com/mailgun/oxy/roundrobin" "net/http" "strings" "time" + + log "github.com/Sirupsen/logrus" + "github.com/mailgun/oxy/roundrobin" ) +// WebsocketUpgrader holds Websocket configuration. type WebsocketUpgrader struct { rr *roundrobin.RoundRobin } +// NewWebsocketUpgrader returns a new WebsocketUpgrader. func NewWebsocketUpgrader(rr *roundrobin.RoundRobin) *WebsocketUpgrader { wu := WebsocketUpgrader{ rr: rr, From 89bb1ae835953353ed3e0e3965e16dffa77e12d1 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Sun, 1 Nov 2015 19:29:47 +0100 Subject: [PATCH 2/3] Linting provider package Signed-off-by: Vincent Demeester --- provider/boltdb.go | 3 ++ provider/consul.go | 3 ++ provider/docker.go | 90 ++++++++++++++++++++++++-------------------- provider/etcd.go | 3 ++ provider/file.go | 9 +++-- provider/kv.go | 9 +++-- provider/marathon.go | 9 ++++- provider/provider.go | 3 ++ provider/zk.go | 3 ++ 9 files changed, 84 insertions(+), 48 deletions(-) diff --git a/provider/boltdb.go b/provider/boltdb.go index ab4ea3c44..ecad47497 100644 --- a/provider/boltdb.go +++ b/provider/boltdb.go @@ -2,6 +2,7 @@ package provider import "github.com/emilevauge/traefik/types" +// BoltDb holds configurations of the BoltDb provider. type BoltDb struct { Watch bool Endpoint string @@ -10,6 +11,8 @@ type BoltDb struct { KvProvider *Kv } +// Provide allows the provider to provide configurations to traefik +// using the given configuration channel. func (provider *BoltDb) Provide(configurationChan chan<- types.ConfigMessage) error { provider.KvProvider = NewBoltDbProvider(provider) return provider.KvProvider.provide(configurationChan) diff --git a/provider/consul.go b/provider/consul.go index b57fb366d..7f46d3ba5 100644 --- a/provider/consul.go +++ b/provider/consul.go @@ -2,6 +2,7 @@ package provider import "github.com/emilevauge/traefik/types" +// Consul holds configurations of the Consul provider. type Consul struct { Watch bool Endpoint string @@ -10,6 +11,8 @@ type Consul struct { KvProvider *Kv } +// Provide allows the provider to provide configurations to traefik +// using the given configuration channel. func (provider *Consul) Provide(configurationChan chan<- types.ConfigMessage) error { provider.KvProvider = NewConsulProvider(provider) return provider.KvProvider.provide(configurationChan) diff --git a/provider/docker.go b/provider/docker.go index 03cb30e9b..8707c1c74 100644 --- a/provider/docker.go +++ b/provider/docker.go @@ -18,6 +18,7 @@ import ( "github.com/fsouza/go-dockerclient" ) +// Docker holds configurations of the Docker provider. type Docker struct { Watch bool Endpoint string @@ -25,51 +26,54 @@ type Docker struct { Domain string } +// Provide allows the provider to provide configurations to traefik +// using the given configuration channel. func (provider *Docker) Provide(configurationChan chan<- types.ConfigMessage) error { - if dockerClient, err := docker.NewClient(provider.Endpoint); err != nil { + + dockerClient, err := docker.NewClient(provider.Endpoint) + if err != nil { log.Errorf("Failed to create a client for docker, error: %s", err) return err - } else { - err := dockerClient.Ping() - if err != nil { - log.Errorf("Docker connection error %+v", err) - return err - } - log.Debug("Docker connection established") - if provider.Watch { - dockerEvents := make(chan *docker.APIEvents) - dockerClient.AddEventListener(dockerEvents) - log.Debug("Docker listening") - go func() { - operation := func() error { - for { - event := <-dockerEvents - if event == nil { - return errors.New("Docker event nil") - // log.Fatalf("Docker connection error") - } - if event.Status == "start" || event.Status == "die" { - log.Debugf("Docker event receveived %+v", event) - configuration := provider.loadDockerConfig(dockerClient) - if configuration != nil { - configurationChan <- types.ConfigMessage{"docker", configuration} - } + } + err = dockerClient.Ping() + if err != nil { + log.Errorf("Docker connection error %+v", err) + return err + } + log.Debug("Docker connection established") + if provider.Watch { + dockerEvents := make(chan *docker.APIEvents) + dockerClient.AddEventListener(dockerEvents) + log.Debug("Docker listening") + go func() { + operation := func() error { + for { + event := <-dockerEvents + if event == nil { + return errors.New("Docker event nil") + // log.Fatalf("Docker connection error") + } + if event.Status == "start" || event.Status == "die" { + log.Debugf("Docker event receveived %+v", event) + configuration := provider.loadDockerConfig(dockerClient) + if configuration != nil { + configurationChan <- types.ConfigMessage{"docker", configuration} } } } - notify := func(err error, time time.Duration) { - log.Errorf("Docker connection error %+v, retrying in %s", err, time) - } - err := backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify) - if err != nil { - log.Fatalf("Cannot connect to docker server %+v", err) - } - }() - } - - configuration := provider.loadDockerConfig(dockerClient) - configurationChan <- types.ConfigMessage{"docker", configuration} + } + notify := func(err error, time time.Duration) { + log.Errorf("Docker connection error %+v, retrying in %s", err, time) + } + err := backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify) + if err != nil { + log.Fatalf("Cannot connect to docker server %+v", err) + } + }() } + + configuration := provider.loadDockerConfig(dockerClient) + configurationChan <- types.ConfigMessage{"docker", configuration} return nil } @@ -223,15 +227,17 @@ func (provider *Docker) getLabel(container docker.Container, label string) (stri func (provider *Docker) getLabels(container docker.Container, labels []string) (map[string]string, error) { foundLabels := map[string]string{} for _, label := range labels { - if foundLabel, err := provider.getLabel(container, label); err != nil { + foundLabel, err := provider.getLabel(container, label) + if err != nil { return nil, errors.New("Label not found: " + label) - } else { - foundLabels[label] = foundLabel } + foundLabels[label] = foundLabel } return foundLabels, nil } +// GetFrontendValue returns the frontend value for the specified container, using +// it's label. It returns a default one if the label is not present. func (provider *Docker) GetFrontendValue(container docker.Container) string { if label, err := provider.getLabel(container, "traefik.frontend.value"); err == nil { return label @@ -239,6 +245,8 @@ func (provider *Docker) GetFrontendValue(container docker.Container) string { return provider.getEscapedName(container.Name) + "." + provider.Domain } +// GetFrontendRule returns the frontend rule for the specified container, using +// it's label. It returns a default one (Host) if the label is not present. func (provider *Docker) GetFrontendRule(container docker.Container) string { if label, err := provider.getLabel(container, "traefik.frontend.rule"); err == nil { return label diff --git a/provider/etcd.go b/provider/etcd.go index e2edee7cb..82eb32abf 100644 --- a/provider/etcd.go +++ b/provider/etcd.go @@ -2,6 +2,7 @@ package provider import "github.com/emilevauge/traefik/types" +// Etcd holds configurations of the Etcd provider. type Etcd struct { Watch bool Endpoint string @@ -10,6 +11,8 @@ type Etcd struct { KvProvider *Kv } +// Provide allows the provider to provide configurations to traefik +// using the given configuration channel. func (provider *Etcd) Provide(configurationChan chan<- types.ConfigMessage) error { provider.KvProvider = NewEtcdProvider(provider) return provider.KvProvider.provide(configurationChan) diff --git a/provider/file.go b/provider/file.go index a85e95011..0e1c2c091 100644 --- a/provider/file.go +++ b/provider/file.go @@ -11,11 +11,14 @@ import ( "gopkg.in/fsnotify.v1" ) +// File holds configurations of the File provider. type File struct { Watch bool Filename string } +// Provide allows the provider to provide configurations to traefik +// using the given configuration channel. func (provider *File) Provide(configurationChan chan<- types.ConfigMessage) error { watcher, err := fsnotify.NewWatcher() if err != nil { @@ -39,7 +42,7 @@ func (provider *File) Provide(configurationChan chan<- types.ConfigMessage) erro case event := <-watcher.Events: if strings.Contains(event.Name, file.Name()) { log.Debug("File event:", event) - configuration := provider.LoadFileConfig(file.Name()) + configuration := provider.loadFileConfig(file.Name()) if configuration != nil { configurationChan <- types.ConfigMessage{"file", configuration} } @@ -56,12 +59,12 @@ func (provider *File) Provide(configurationChan chan<- types.ConfigMessage) erro } } - configuration := provider.LoadFileConfig(file.Name()) + configuration := provider.loadFileConfig(file.Name()) configurationChan <- types.ConfigMessage{"file", configuration} return nil } -func (provider *File) LoadFileConfig(filename string) *types.Configuration { +func (provider *File) loadFileConfig(filename string) *types.Configuration { configuration := new(types.Configuration) if _, err := toml.DecodeFile(filename, configuration); err != nil { log.Error("Error reading file:", err) diff --git a/provider/kv.go b/provider/kv.go index 1b260e039..1690735a3 100644 --- a/provider/kv.go +++ b/provider/kv.go @@ -1,6 +1,4 @@ -/* -Copyright -*/ +// Package provider holds the different provider implementation. package provider import ( @@ -23,6 +21,7 @@ import ( "github.com/emilevauge/traefik/types" ) +// Kv holds common configurations of key-value providers. type Kv struct { Watch bool Endpoint string @@ -32,6 +31,7 @@ type Kv struct { kvclient store.Store } +// NewConsulProvider returns a Consul provider. func NewConsulProvider(provider *Consul) *Kv { kvProvider := new(Kv) kvProvider.Watch = provider.Watch @@ -42,6 +42,7 @@ func NewConsulProvider(provider *Consul) *Kv { return kvProvider } +// NewEtcdProvider returns a Etcd provider. func NewEtcdProvider(provider *Etcd) *Kv { kvProvider := new(Kv) kvProvider.Watch = provider.Watch @@ -52,6 +53,7 @@ func NewEtcdProvider(provider *Etcd) *Kv { return kvProvider } +// NewZkProvider returns a Zookepper provider. func NewZkProvider(provider *Zookepper) *Kv { kvProvider := new(Kv) kvProvider.Watch = provider.Watch @@ -62,6 +64,7 @@ func NewZkProvider(provider *Zookepper) *Kv { return kvProvider } +// NewBoltDbProvider returns a BoldDb provider. func NewBoltDbProvider(provider *BoltDb) *Kv { kvProvider := new(Kv) kvProvider.Watch = provider.Watch diff --git a/provider/marathon.go b/provider/marathon.go index c45affb73..890be561c 100644 --- a/provider/marathon.go +++ b/provider/marathon.go @@ -15,15 +15,18 @@ import ( "github.com/gambol99/go-marathon" ) +// Marathon holds configuration of the Marathon provider. type Marathon struct { Watch bool Endpoint string - marathonClient marathon.Marathon Domain string Filename string NetworkInterface string + marathonClient marathon.Marathon } +// Provide allows the provider to provide configurations to traefik +// using the given configuration channel. func (provider *Marathon) Provide(configurationChan chan<- types.ConfigMessage) error { config := marathon.NewDefaultConfig() config.URL = provider.Endpoint @@ -238,6 +241,8 @@ func (provider *Marathon) getEscapedName(name string) string { return strings.Replace(name, "/", "", -1) } +// GetFrontendValue returns the frontend value for the specified application, using +// it's label. It returns a default one if the label is not present. func (provider *Marathon) GetFrontendValue(application marathon.Application) string { if label, err := provider.getLabel(application, "traefik.frontend.value"); err == nil { return label @@ -245,6 +250,8 @@ func (provider *Marathon) GetFrontendValue(application marathon.Application) str return provider.getEscapedName(application.ID) + "." + provider.Domain } +// GetFrontendRule returns the frontend rule for the specified application, using +// it's label. It returns a default one (Host) if the label is not present. func (provider *Marathon) GetFrontendRule(application marathon.Application) string { if label, err := provider.getLabel(application, "traefik.frontend.rule"); err == nil { return label diff --git a/provider/provider.go b/provider/provider.go index 4b7dc2702..f1001a953 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -2,6 +2,9 @@ package provider import "github.com/emilevauge/traefik/types" +// Provider defines methods of a provider. type Provider interface { + // Provide allows the provider to provide configurations to traefik + // using the given configuration channel. Provide(configurationChan chan<- types.ConfigMessage) error } diff --git a/provider/zk.go b/provider/zk.go index c40bd7c93..1b5079526 100644 --- a/provider/zk.go +++ b/provider/zk.go @@ -2,6 +2,7 @@ package provider import "github.com/emilevauge/traefik/types" +// Zookepper holds configurations of the Zookepper provider. type Zookepper struct { Watch bool Endpoint string @@ -10,6 +11,8 @@ type Zookepper struct { KvProvider *Kv } +// Provide allows the provider to provide configurations to traefik +// using the given configuration channel. func (provider *Zookepper) Provide(configurationChan chan<- types.ConfigMessage) error { provider.KvProvider = NewZkProvider(provider) return provider.KvProvider.provide(configurationChan) From c32f82baeed4e6a7e909c3ce6cff668ba4a895a6 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Sun, 1 Nov 2015 19:15:05 +0100 Subject: [PATCH 3/3] Linting types package Signed-off-by: Vincent Demeester --- types/types.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/types/types.go b/types/types.go index 41cdea240..22abb8dd2 100644 --- a/types/types.go +++ b/types/types.go @@ -5,43 +5,43 @@ import ( "strings" ) -// Backend configuration +// Backend holds backend configuration. type Backend struct { Servers map[string]Server `json:"servers,omitempty"` CircuitBreaker *CircuitBreaker `json:"circuitBreaker,omitempty"` LoadBalancer *LoadBalancer `json:"loadBalancer,omitempty"` } -// LoadBalancer configuration +// LoadBalancer holds load balancing configuration. type LoadBalancer struct { Method string `json:"method,omitempty"` } -// CircuitBreaker configuration +// CircuitBreaker holds circuit breaker configuration. type CircuitBreaker struct { Expression string `json:"expression,omitempty"` } -// Server configuration +// Server holds server configuration. type Server struct { URL string `json:"url,omitempty"` Weight int `json:"weight,omitempty"` } -// Route configuration +// Route holds route configuration. type Route struct { Rule string `json:"rule,omitempty"` Value string `json:"value,omitempty"` } -// Frontend configuration +// Frontend holds frontend configuration. type Frontend struct { Backend string `json:"backend,omitempty"` Routes map[string]Route `json:"routes,omitempty"` PassHostHeader bool `json:"passHostHeader,omitempty"` } -// Load Balancer Method +// LoadBalancerMethod holds the method of load balancing to use. type LoadBalancerMethod uint8 const ( @@ -56,6 +56,7 @@ var loadBalancerMethodNames = []string{ "Drr", } +// NewLoadBalancerMethod create a new LoadBalancerMethod from a given LoadBalancer. func NewLoadBalancerMethod(loadBalancer *LoadBalancer) (LoadBalancerMethod, error) { if loadBalancer != nil { for i, name := range loadBalancerMethodNames { @@ -67,14 +68,16 @@ func NewLoadBalancerMethod(loadBalancer *LoadBalancer) (LoadBalancerMethod, erro return Wrr, ErrInvalidLoadBalancerMethod } +// ErrInvalidLoadBalancerMethod is thrown when the specified load balancing method is invalid. var ErrInvalidLoadBalancerMethod = errors.New("Invalid method, using default") -// Configuration of a provider +// Configuration of a provider. type Configuration struct { Backends map[string]*Backend `json:"backends,omitempty"` Frontends map[string]*Frontend `json:"frontends,omitempty"` } +// ConfigMessage hold configuration information exchanged between parts of traefik. type ConfigMessage struct { ProviderName string Configuration *Configuration