Flaeg integration
This commit is contained in:
parent
7804787e9e
commit
fe0a8f3363
16 changed files with 361 additions and 401 deletions
230
cmd.go
230
cmd.go
|
@ -1,230 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright
|
|
||||||
*/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
fmtlog "log"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"github.com/containous/traefik/middlewares"
|
|
||||||
"github.com/containous/traefik/provider"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
var traefikCmd = &cobra.Command{
|
|
||||||
Use: "traefik",
|
|
||||||
Short: "traefik, a modern reverse proxy",
|
|
||||||
Long: `traefik is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.
|
|
||||||
Complete documentation is available at http://traefik.io`,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
run()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
var versionCmd = &cobra.Command{
|
|
||||||
Use: "version",
|
|
||||||
Short: "Print version",
|
|
||||||
Long: `Print version`,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmtlog.Println(Version + " built on the " + BuildDate)
|
|
||||||
os.Exit(0)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var arguments = struct {
|
|
||||||
GlobalConfiguration
|
|
||||||
web bool
|
|
||||||
file bool
|
|
||||||
docker bool
|
|
||||||
dockerTLS bool
|
|
||||||
marathon bool
|
|
||||||
consul bool
|
|
||||||
consulTLS bool
|
|
||||||
consulCatalog bool
|
|
||||||
zookeeper bool
|
|
||||||
etcd bool
|
|
||||||
etcdTLS bool
|
|
||||||
boltdb bool
|
|
||||||
kubernetes bool
|
|
||||||
}{
|
|
||||||
GlobalConfiguration{
|
|
||||||
EntryPoints: make(EntryPoints),
|
|
||||||
Docker: &provider.Docker{
|
|
||||||
TLS: &provider.DockerTLS{},
|
|
||||||
},
|
|
||||||
File: &provider.File{},
|
|
||||||
Web: &WebProvider{},
|
|
||||||
Marathon: &provider.Marathon{},
|
|
||||||
Consul: &provider.Consul{
|
|
||||||
Kv: provider.Kv{
|
|
||||||
TLS: &provider.KvTLS{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ConsulCatalog: &provider.ConsulCatalog{},
|
|
||||||
Zookeeper: &provider.Zookepper{},
|
|
||||||
Etcd: &provider.Etcd{
|
|
||||||
Kv: provider.Kv{
|
|
||||||
TLS: &provider.KvTLS{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Boltdb: &provider.BoltDb{},
|
|
||||||
Kubernetes: &provider.Kubernetes{},
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
traefikCmd.AddCommand(versionCmd)
|
|
||||||
traefikCmd.PersistentFlags().StringP("configFile", "c", "", "Configuration file to use (TOML).")
|
|
||||||
traefikCmd.PersistentFlags().BoolVarP(&arguments.Debug, "debug", "d", false, "Enable debug mode")
|
|
||||||
traefikCmd.PersistentFlags().StringP("graceTimeOut", "g", "10", "Timeout in seconds. Duration to give active requests a chance to finish during hot-reloads")
|
|
||||||
traefikCmd.PersistentFlags().String("accessLogsFile", "log/access.log", "Access logs file")
|
|
||||||
traefikCmd.PersistentFlags().String("traefikLogsFile", "log/traefik.log", "Traefik logs file")
|
|
||||||
traefikCmd.PersistentFlags().Var(&arguments.EntryPoints, "entryPoints", "Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key'")
|
|
||||||
traefikCmd.PersistentFlags().Var(&arguments.DefaultEntryPoints, "defaultEntryPoints", "Entrypoints to be used by frontends that do not specify any entrypoint")
|
|
||||||
traefikCmd.PersistentFlags().StringP("logLevel", "l", "ERROR", "Log level")
|
|
||||||
traefikCmd.PersistentFlags().DurationVar(&arguments.ProvidersThrottleDuration, "providersThrottleDuration", time.Duration(2*time.Second), "Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time.")
|
|
||||||
traefikCmd.PersistentFlags().Int("maxIdleConnsPerHost", 0, "If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used")
|
|
||||||
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.web, "web", false, "Enable Web backend")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Web.Address, "web.address", ":8080", "Web administration port")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Web.CertFile, "web.cerFile", "", "SSL certificate")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Web.KeyFile, "web.keyFile", "", "SSL certificate")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.Web.ReadOnly, "web.readOnly", false, "Enable read only API")
|
|
||||||
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.file, "file", false, "Enable File backend")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.File.Watch, "file.watch", true, "Watch provider")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.File.Filename, "file.filename", "", "Override default configuration template. For advanced users :)")
|
|
||||||
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.docker, "docker", false, "Enable Docker backend")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.Docker.Watch, "docker.watch", true, "Watch provider")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Docker.Filename, "docker.filename", "", "Override default configuration template. For advanced users :)")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Docker.Endpoint, "docker.endpoint", "unix:///var/run/docker.sock", "Docker server endpoint. Can be a tcp or a unix socket endpoint")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Docker.Domain, "docker.domain", "", "Default domain used")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.dockerTLS, "docker.tls", false, "Enable Docker TLS support")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Docker.TLS.CA, "docker.tls.ca", "", "TLS CA")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Docker.TLS.Cert, "docker.tls.cert", "", "TLS cert")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Docker.TLS.Key, "docker.tls.key", "", "TLS key")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.Docker.TLS.InsecureSkipVerify, "docker.tls.insecureSkipVerify", false, "TLS insecure skip verify")
|
|
||||||
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.marathon, "marathon", false, "Enable Marathon backend")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.Marathon.Watch, "marathon.watch", true, "Watch provider")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Marathon.Filename, "marathon.filename", "", "Override default configuration template. For advanced users :)")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Marathon.Endpoint, "marathon.endpoint", "http://127.0.0.1:8080", "Marathon server endpoint. You can also specify multiple endpoint for Marathon")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Marathon.Domain, "marathon.domain", "", "Default domain used")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.Marathon.ExposedByDefault, "marathon.exposedByDefault", true, "Expose Marathon apps by default")
|
|
||||||
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.consul, "consul", false, "Enable Consul backend")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.Consul.Watch, "consul.watch", true, "Watch provider")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.Filename, "consul.filename", "", "Override default configuration template. For advanced users :)")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.Endpoint, "consul.endpoint", "127.0.0.1:8500", "Comma sepparated Consul server endpoints")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.Prefix, "consul.prefix", "/traefik", "Prefix used for KV store")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.consulTLS, "consul.tls", false, "Enable Consul TLS support")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.TLS.CA, "consul.tls.ca", "", "TLS CA")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.TLS.Cert, "consul.tls.cert", "", "TLS cert")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.TLS.Key, "consul.tls.key", "", "TLS key")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.Consul.TLS.InsecureSkipVerify, "consul.tls.insecureSkipVerify", false, "TLS insecure skip verify")
|
|
||||||
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.consulCatalog, "consulCatalog", false, "Enable Consul catalog backend")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.ConsulCatalog.Domain, "consulCatalog.domain", "", "Default domain used")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.ConsulCatalog.Endpoint, "consulCatalog.endpoint", "127.0.0.1:8500", "Consul server endpoint")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.ConsulCatalog.Prefix, "consulCatalog.prefix", "traefik", "Consul catalog tag prefix")
|
|
||||||
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.zookeeper, "zookeeper", false, "Enable Zookeeper backend")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.Zookeeper.Watch, "zookeeper.watch", true, "Watch provider")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Zookeeper.Filename, "zookeeper.filename", "", "Override default configuration template. For advanced users :)")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Zookeeper.Endpoint, "zookeeper.endpoint", "127.0.0.1:2181", "Comma sepparated Zookeeper server endpoints")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Zookeeper.Prefix, "zookeeper.prefix", "/traefik", "Prefix used for KV store")
|
|
||||||
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.etcd, "etcd", false, "Enable Etcd backend")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.Etcd.Watch, "etcd.watch", true, "Watch provider")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.Filename, "etcd.filename", "", "Override default configuration template. For advanced users :)")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.Endpoint, "etcd.endpoint", "127.0.0.1:4001", "Comma sepparated Etcd server endpoints")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.Prefix, "etcd.prefix", "/traefik", "Prefix used for KV store")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.etcdTLS, "etcd.tls", false, "Enable Etcd TLS support")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.TLS.CA, "etcd.tls.ca", "", "TLS CA")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.TLS.Cert, "etcd.tls.cert", "", "TLS cert")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.TLS.Key, "etcd.tls.key", "", "TLS key")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.Etcd.TLS.InsecureSkipVerify, "etcd.tls.insecureSkipVerify", false, "TLS insecure skip verify")
|
|
||||||
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.boltdb, "boltdb", false, "Enable Boltdb backend")
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.Boltdb.Watch, "boltdb.watch", true, "Watch provider")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Boltdb.Filename, "boltdb.filename", "", "Override default configuration template. For advanced users :)")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Boltdb.Endpoint, "boltdb.endpoint", "127.0.0.1:4001", "Boltdb server endpoint")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Boltdb.Prefix, "boltdb.prefix", "/traefik", "Prefix used for KV store")
|
|
||||||
|
|
||||||
traefikCmd.PersistentFlags().BoolVar(&arguments.kubernetes, "kubernetes", false, "Enable Kubernetes backend")
|
|
||||||
traefikCmd.PersistentFlags().StringVar(&arguments.Kubernetes.Endpoint, "kubernetes.endpoint", "http://127.0.0.1:8080", "Kubernetes server endpoint")
|
|
||||||
traefikCmd.PersistentFlags().StringSliceVar(&arguments.Kubernetes.Namespaces, "kubernetes.namespaces", []string{}, "Kubernetes namespaces")
|
|
||||||
|
|
||||||
_ = viper.BindPFlag("configFile", traefikCmd.PersistentFlags().Lookup("configFile"))
|
|
||||||
_ = viper.BindPFlag("graceTimeOut", traefikCmd.PersistentFlags().Lookup("graceTimeOut"))
|
|
||||||
_ = viper.BindPFlag("logLevel", traefikCmd.PersistentFlags().Lookup("logLevel"))
|
|
||||||
_ = viper.BindPFlag("debug", traefikCmd.PersistentFlags().Lookup("debug"))
|
|
||||||
// TODO: wait for this issue to be corrected: https://github.com/spf13/viper/issues/105
|
|
||||||
_ = viper.BindPFlag("providersThrottleDuration", traefikCmd.PersistentFlags().Lookup("providersThrottleDuration"))
|
|
||||||
_ = viper.BindPFlag("maxIdleConnsPerHost", traefikCmd.PersistentFlags().Lookup("maxIdleConnsPerHost"))
|
|
||||||
viper.SetDefault("providersThrottleDuration", time.Duration(2*time.Second))
|
|
||||||
viper.SetDefault("logLevel", "ERROR")
|
|
||||||
viper.SetDefault("MaxIdleConnsPerHost", 200)
|
|
||||||
}
|
|
||||||
|
|
||||||
func run() {
|
|
||||||
fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags)
|
|
||||||
|
|
||||||
// load global configuration
|
|
||||||
globalConfiguration := LoadConfiguration()
|
|
||||||
|
|
||||||
http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost = globalConfiguration.MaxIdleConnsPerHost
|
|
||||||
loggerMiddleware := middlewares.NewLogger(globalConfiguration.AccessLogsFile)
|
|
||||||
defer loggerMiddleware.Close()
|
|
||||||
|
|
||||||
// logging
|
|
||||||
level, err := log.ParseLevel(strings.ToLower(globalConfiguration.LogLevel))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Error getting level", err)
|
|
||||||
}
|
|
||||||
log.SetLevel(level)
|
|
||||||
|
|
||||||
if len(globalConfiguration.TraefikLogsFile) > 0 {
|
|
||||||
fi, err := os.OpenFile(globalConfiguration.TraefikLogsFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
|
||||||
defer func() {
|
|
||||||
if err := fi.Close(); err != nil {
|
|
||||||
log.Error("Error closinf file", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Error opening file", err)
|
|
||||||
} else {
|
|
||||||
log.SetOutput(fi)
|
|
||||||
log.SetFormatter(&log.TextFormatter{DisableColors: true, FullTimestamp: true, DisableSorting: true})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.SetFormatter(&log.TextFormatter{FullTimestamp: true, DisableSorting: true})
|
|
||||||
}
|
|
||||||
jsonConf, _ := json.Marshal(globalConfiguration)
|
|
||||||
log.Debugf("Global configuration loaded %s", string(jsonConf))
|
|
||||||
server := NewServer(*globalConfiguration)
|
|
||||||
server.Start()
|
|
||||||
defer server.Close()
|
|
||||||
log.Info("Shutting down")
|
|
||||||
}
|
|
266
configuration.go
266
configuration.go
|
@ -3,42 +3,44 @@ package main
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
fmtlog "log"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containous/traefik/acme"
|
"github.com/containous/traefik/acme"
|
||||||
"github.com/containous/traefik/provider"
|
"github.com/containous/traefik/provider"
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
"github.com/mitchellh/mapstructure"
|
"regexp"
|
||||||
"github.com/spf13/viper"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TraefikConfiguration holds GlobalConfiguration and other stuff
|
||||||
|
type TraefikConfiguration struct {
|
||||||
|
GlobalConfiguration
|
||||||
|
ConfigFile string `short:"c" description:"Timeout in seconds. Duration to give active requests a chance to finish during hot-reloads"`
|
||||||
|
}
|
||||||
|
|
||||||
// GlobalConfiguration holds global configuration (with providers, etc.).
|
// GlobalConfiguration holds global configuration (with providers, etc.).
|
||||||
// It's populated from the traefik configuration file passed as an argument to the binary.
|
// It's populated from the traefik configuration file passed as an argument to the binary.
|
||||||
type GlobalConfiguration struct {
|
type GlobalConfiguration struct {
|
||||||
GraceTimeOut int64
|
GraceTimeOut int64 `short:"g" description:"Configuration file to use (TOML)."`
|
||||||
Debug bool
|
Debug bool
|
||||||
AccessLogsFile string
|
AccessLogsFile string `description:"Access logs file"`
|
||||||
TraefikLogsFile string
|
TraefikLogsFile string `description:"Traefik logs file"`
|
||||||
LogLevel string
|
LogLevel string `short:"l" description:"Log level"`
|
||||||
EntryPoints EntryPoints
|
EntryPoints EntryPoints `description:"Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key'"`
|
||||||
ACME *acme.ACME
|
ACME *acme.ACME
|
||||||
DefaultEntryPoints DefaultEntryPoints
|
DefaultEntryPoints DefaultEntryPoints `description:"Entrypoints to be used by frontends that do not specify any entrypoint"`
|
||||||
ProvidersThrottleDuration time.Duration
|
ProvidersThrottleDuration time.Duration `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time."`
|
||||||
MaxIdleConnsPerHost int
|
MaxIdleConnsPerHost int `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used"`
|
||||||
Retry *Retry
|
Retry *Retry
|
||||||
Docker *provider.Docker
|
Docker *provider.Docker `description:"Enable Docker backend"`
|
||||||
File *provider.File
|
File *provider.File `description:"Enable File backend"`
|
||||||
Web *WebProvider
|
Web *WebProvider `description:"Enable Web backend"`
|
||||||
Marathon *provider.Marathon
|
Marathon *provider.Marathon `description:"Enable Marathon backend"`
|
||||||
Consul *provider.Consul
|
Consul *provider.Consul `description:"Enable Consul backend"`
|
||||||
ConsulCatalog *provider.ConsulCatalog
|
ConsulCatalog *provider.ConsulCatalog `description:"Enable Consul catalog backend"`
|
||||||
Etcd *provider.Etcd
|
Etcd *provider.Etcd `description:"Enable Etcd backend"`
|
||||||
Zookeeper *provider.Zookepper
|
Zookeeper *provider.Zookepper `description:"Enable Zookeeper backend"`
|
||||||
Boltdb *provider.BoltDb
|
Boltdb *provider.BoltDb `description:"Enable Boltdb backend"`
|
||||||
Kubernetes *provider.Kubernetes
|
Kubernetes *provider.Kubernetes `description:"Enable Kubernetes backend"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultEntryPoints holds default entry points
|
// DefaultEntryPoints holds default entry points
|
||||||
|
@ -47,6 +49,7 @@ type DefaultEntryPoints []string
|
||||||
// String is the method to format the flag's value, part of the flag.Value interface.
|
// String is the method to format the flag's value, part of the flag.Value interface.
|
||||||
// The String method's output will be used in diagnostics.
|
// The String method's output will be used in diagnostics.
|
||||||
func (dep *DefaultEntryPoints) String() string {
|
func (dep *DefaultEntryPoints) String() string {
|
||||||
|
//TODO :
|
||||||
return fmt.Sprintf("%#v", dep)
|
return fmt.Sprintf("%#v", dep)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +67,14 @@ func (dep *DefaultEntryPoints) Set(value string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get return the EntryPoints map
|
||||||
|
func (dep *DefaultEntryPoints) Get() interface{} { return DefaultEntryPoints(*dep) }
|
||||||
|
|
||||||
|
// SetValue sets the EntryPoints map with val
|
||||||
|
func (dep *DefaultEntryPoints) SetValue(val interface{}) {
|
||||||
|
*dep = DefaultEntryPoints(val.(DefaultEntryPoints))
|
||||||
|
}
|
||||||
|
|
||||||
// Type is type of the struct
|
// Type is type of the struct
|
||||||
func (dep *DefaultEntryPoints) Type() string {
|
func (dep *DefaultEntryPoints) Type() string {
|
||||||
return fmt.Sprint("defaultentrypoints²")
|
return fmt.Sprint("defaultentrypoints²")
|
||||||
|
@ -75,6 +86,7 @@ type EntryPoints map[string]*EntryPoint
|
||||||
// String is the method to format the flag's value, part of the flag.Value interface.
|
// String is the method to format the flag's value, part of the flag.Value interface.
|
||||||
// The String method's output will be used in diagnostics.
|
// The String method's output will be used in diagnostics.
|
||||||
func (ep *EntryPoints) String() string {
|
func (ep *EntryPoints) String() string {
|
||||||
|
//TODO :
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,6 +134,14 @@ func (ep *EntryPoints) Set(value string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get return the EntryPoints map
|
||||||
|
func (ep *EntryPoints) Get() interface{} { return EntryPoints(*ep) }
|
||||||
|
|
||||||
|
// SetValue sets the EntryPoints map with val
|
||||||
|
func (ep *EntryPoints) SetValue(val interface{}) {
|
||||||
|
*ep = EntryPoints(val.(EntryPoints))
|
||||||
|
}
|
||||||
|
|
||||||
// Type is type of the struct
|
// Type is type of the struct
|
||||||
func (ep *EntryPoints) Type() string {
|
func (ep *EntryPoints) Type() string {
|
||||||
return fmt.Sprint("entrypoints²")
|
return fmt.Sprint("entrypoints²")
|
||||||
|
@ -154,6 +174,7 @@ type Certificates []Certificate
|
||||||
// The String method's output will be used in diagnostics.
|
// The String method's output will be used in diagnostics.
|
||||||
func (certs *Certificates) String() string {
|
func (certs *Certificates) String() string {
|
||||||
if len(*certs) == 0 {
|
if len(*certs) == 0 {
|
||||||
|
//TODO :
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return (*certs)[0].CertFile + "," + (*certs)[0].KeyFile
|
return (*certs)[0].CertFile + "," + (*certs)[0].KeyFile
|
||||||
|
@ -191,117 +212,96 @@ type Retry struct {
|
||||||
MaxMem int64
|
MaxMem int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGlobalConfiguration returns a GlobalConfiguration with default values.
|
// NewTraefikPointersConfiguration creates a TraefikConfiguration with pointers default values
|
||||||
func NewGlobalConfiguration() *GlobalConfiguration {
|
func NewTraefikPointersConfiguration() *TraefikConfiguration {
|
||||||
return new(GlobalConfiguration)
|
//default Docker
|
||||||
|
var defaultDocker provider.Docker
|
||||||
|
defaultDocker.Watch = true
|
||||||
|
defaultDocker.Endpoint = "unix:///var/run/docker.sock"
|
||||||
|
defaultDocker.TLS = &provider.DockerTLS{}
|
||||||
|
|
||||||
|
// default File
|
||||||
|
var defaultFile provider.File
|
||||||
|
defaultFile.Watch = true
|
||||||
|
defaultFile.Filename = "" //needs equivalent to viper.ConfigFileUsed()
|
||||||
|
|
||||||
|
// default Web
|
||||||
|
var defaultWeb WebProvider
|
||||||
|
defaultWeb.Address = ":8080"
|
||||||
|
|
||||||
|
// default Marathon
|
||||||
|
var defaultMarathon provider.Marathon
|
||||||
|
defaultMarathon.Watch = true
|
||||||
|
defaultMarathon.Endpoint = "http://127.0.0.1:8080"
|
||||||
|
defaultMarathon.ExposedByDefault = true
|
||||||
|
|
||||||
|
// default Consul
|
||||||
|
var defaultConsul provider.Consul
|
||||||
|
defaultConsul.Watch = true
|
||||||
|
defaultConsul.Endpoint = "127.0.0.1:8500"
|
||||||
|
defaultConsul.Prefix = "/traefik"
|
||||||
|
defaultConsul.TLS = &provider.KvTLS{}
|
||||||
|
|
||||||
|
// default ConsulCatalog
|
||||||
|
var defaultConsulCatalog provider.ConsulCatalog
|
||||||
|
defaultConsulCatalog.Endpoint = "127.0.0.1:8500"
|
||||||
|
|
||||||
|
// default Etcd
|
||||||
|
var defaultEtcd provider.Etcd
|
||||||
|
defaultEtcd.Watch = true
|
||||||
|
defaultEtcd.Endpoint = "127.0.0.1:400"
|
||||||
|
defaultEtcd.Prefix = "/traefik"
|
||||||
|
defaultEtcd.TLS = &provider.KvTLS{}
|
||||||
|
|
||||||
|
//default Zookeeper
|
||||||
|
var defaultZookeeper provider.Zookepper
|
||||||
|
defaultZookeeper.Watch = true
|
||||||
|
defaultZookeeper.Endpoint = "127.0.0.1:2181"
|
||||||
|
defaultZookeeper.Prefix = "/traefik"
|
||||||
|
|
||||||
|
//default Boltdb
|
||||||
|
var defaultBoltDb provider.BoltDb
|
||||||
|
defaultBoltDb.Watch = true
|
||||||
|
defaultBoltDb.Endpoint = "127.0.0.1:4001"
|
||||||
|
defaultBoltDb.Prefix = "/traefik"
|
||||||
|
|
||||||
|
//default Kubernetes
|
||||||
|
var defaultKubernetes provider.Kubernetes
|
||||||
|
defaultKubernetes.Watch = true
|
||||||
|
defaultKubernetes.Endpoint = "127.0.0.1:8080"
|
||||||
|
|
||||||
|
defaultConfiguration := GlobalConfiguration{
|
||||||
|
Docker: &defaultDocker,
|
||||||
|
File: &defaultFile,
|
||||||
|
Web: &defaultWeb,
|
||||||
|
Marathon: &defaultMarathon,
|
||||||
|
Consul: &defaultConsul,
|
||||||
|
ConsulCatalog: &defaultConsulCatalog,
|
||||||
|
Etcd: &defaultEtcd,
|
||||||
|
Zookeeper: &defaultZookeeper,
|
||||||
|
Boltdb: &defaultBoltDb,
|
||||||
|
Kubernetes: &defaultKubernetes,
|
||||||
|
}
|
||||||
|
return &TraefikConfiguration{
|
||||||
|
GlobalConfiguration: defaultConfiguration,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfiguration returns a GlobalConfiguration.
|
// NewTraefikConfiguration creates a TraefikConfiguration with default values
|
||||||
func LoadConfiguration() *GlobalConfiguration {
|
func NewTraefikConfiguration() *TraefikConfiguration {
|
||||||
configuration := NewGlobalConfiguration()
|
return &TraefikConfiguration{
|
||||||
viper.SetEnvPrefix("traefik")
|
GlobalConfiguration: GlobalConfiguration{
|
||||||
viper.SetConfigType("toml")
|
GraceTimeOut: 10,
|
||||||
viper.AutomaticEnv()
|
AccessLogsFile: "log/access.log",
|
||||||
if len(viper.GetString("configFile")) > 0 {
|
TraefikLogsFile: "log/traefik.log",
|
||||||
viper.SetConfigFile(viper.GetString("configFile"))
|
LogLevel: "ERROR",
|
||||||
} else {
|
EntryPoints: map[string]*EntryPoint{"http": &EntryPoint{Address: ":80"}},
|
||||||
viper.SetConfigName("traefik") // name of config file (without extension)
|
DefaultEntryPoints: []string{"http"},
|
||||||
|
ProvidersThrottleDuration: time.Duration(2 * time.Second),
|
||||||
|
MaxIdleConnsPerHost: 200,
|
||||||
|
},
|
||||||
|
ConfigFile: "",
|
||||||
}
|
}
|
||||||
viper.AddConfigPath("/etc/traefik/") // path to look for the config file in
|
|
||||||
viper.AddConfigPath("$HOME/.traefik/") // call multiple times to add many search paths
|
|
||||||
viper.AddConfigPath(".") // optionally look for config in the working directory
|
|
||||||
if err := viper.ReadInConfig(); err != nil {
|
|
||||||
if len(viper.ConfigFileUsed()) > 0 {
|
|
||||||
fmtlog.Printf("Error reading configuration file: %s", err)
|
|
||||||
} else {
|
|
||||||
fmtlog.Printf("No configuration file found")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(arguments.EntryPoints) > 0 {
|
|
||||||
viper.Set("entryPoints", arguments.EntryPoints)
|
|
||||||
}
|
|
||||||
if len(arguments.DefaultEntryPoints) > 0 {
|
|
||||||
viper.Set("defaultEntryPoints", arguments.DefaultEntryPoints)
|
|
||||||
}
|
|
||||||
if arguments.web {
|
|
||||||
viper.Set("web", arguments.Web)
|
|
||||||
}
|
|
||||||
if arguments.file {
|
|
||||||
viper.Set("file", arguments.File)
|
|
||||||
}
|
|
||||||
if !arguments.dockerTLS {
|
|
||||||
arguments.Docker.TLS = nil
|
|
||||||
}
|
|
||||||
if arguments.docker {
|
|
||||||
viper.Set("docker", arguments.Docker)
|
|
||||||
}
|
|
||||||
if arguments.marathon {
|
|
||||||
viper.Set("marathon", arguments.Marathon)
|
|
||||||
}
|
|
||||||
if !arguments.consulTLS {
|
|
||||||
arguments.Consul.TLS = nil
|
|
||||||
}
|
|
||||||
if arguments.consul {
|
|
||||||
viper.Set("consul", arguments.Consul)
|
|
||||||
}
|
|
||||||
if arguments.consulCatalog {
|
|
||||||
viper.Set("consulCatalog", arguments.ConsulCatalog)
|
|
||||||
}
|
|
||||||
if arguments.zookeeper {
|
|
||||||
viper.Set("zookeeper", arguments.Zookeeper)
|
|
||||||
}
|
|
||||||
if !arguments.etcdTLS {
|
|
||||||
arguments.Etcd.TLS = nil
|
|
||||||
}
|
|
||||||
if arguments.etcd {
|
|
||||||
viper.Set("etcd", arguments.Etcd)
|
|
||||||
}
|
|
||||||
if arguments.boltdb {
|
|
||||||
viper.Set("boltdb", arguments.Boltdb)
|
|
||||||
}
|
|
||||||
if arguments.kubernetes {
|
|
||||||
viper.Set("kubernetes", arguments.Kubernetes)
|
|
||||||
}
|
|
||||||
if err := unmarshal(&configuration); err != nil {
|
|
||||||
|
|
||||||
fmtlog.Fatalf("Error reading file: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(configuration.EntryPoints) == 0 {
|
|
||||||
configuration.EntryPoints = make(map[string]*EntryPoint)
|
|
||||||
configuration.EntryPoints["http"] = &EntryPoint{
|
|
||||||
Address: ":80",
|
|
||||||
}
|
|
||||||
configuration.DefaultEntryPoints = []string{"http"}
|
|
||||||
}
|
|
||||||
|
|
||||||
if configuration.File != nil && len(configuration.File.Filename) == 0 {
|
|
||||||
// no filename, setting to global config file
|
|
||||||
configuration.File.Filename = viper.ConfigFileUsed()
|
|
||||||
}
|
|
||||||
|
|
||||||
return configuration
|
|
||||||
}
|
|
||||||
|
|
||||||
func unmarshal(rawVal interface{}) error {
|
|
||||||
config := &mapstructure.DecoderConfig{
|
|
||||||
DecodeHook: mapstructure.StringToTimeDurationHookFunc(),
|
|
||||||
Metadata: nil,
|
|
||||||
Result: rawVal,
|
|
||||||
WeaklyTypedInput: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
decoder, err := mapstructure.NewDecoder(config)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = decoder.Decode(viper.AllSettings())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type configs map[string]*types.Configuration
|
type configs map[string]*types.Configuration
|
||||||
|
|
91
flaeg_test.go
Normal file
91
flaeg_test.go
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cocap10/flaeg"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoad(t *testing.T) {
|
||||||
|
var configuration GlobalConfiguration
|
||||||
|
defaultConfiguration := NewGlobalConfiguration()
|
||||||
|
args := []string{
|
||||||
|
// "-h",
|
||||||
|
"--docker",
|
||||||
|
"--file",
|
||||||
|
"--web",
|
||||||
|
"--marathon",
|
||||||
|
"--consul",
|
||||||
|
"--consulcatalog",
|
||||||
|
"--etcd",
|
||||||
|
"--zookeeper",
|
||||||
|
"--boltdb",
|
||||||
|
}
|
||||||
|
if err := flaeg.Load(&configuration, defaultConfiguration, args); err != nil {
|
||||||
|
t.Fatalf("Error: %s", err)
|
||||||
|
}
|
||||||
|
// fmt.Printf("result : \n%+v\n", configuration)
|
||||||
|
if !reflect.DeepEqual(configuration, *defaultConfiguration) {
|
||||||
|
t.Fatalf("\nexpected\t: %+v\ngot\t\t\t: %+v", *defaultConfiguration, configuration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadWithParsers(t *testing.T) {
|
||||||
|
var configuration GlobalConfiguration
|
||||||
|
defaultConfiguration := NewGlobalConfiguration()
|
||||||
|
args := []string{
|
||||||
|
// "-h",
|
||||||
|
"--docker",
|
||||||
|
// "--file",
|
||||||
|
"--web.address=:8888",
|
||||||
|
"--marathon",
|
||||||
|
"--consul",
|
||||||
|
"--consulcatalog",
|
||||||
|
"--etcd.tls.insecureskipverify",
|
||||||
|
"--zookeeper",
|
||||||
|
"--boltdb",
|
||||||
|
"--accesslogsfile=log2/access.log",
|
||||||
|
"--entrypoints=Name:http Address::8000 Redirect.EntryPoint:https",
|
||||||
|
"--entrypoints=Name:https Address::8443 Redirect.EntryPoint:http",
|
||||||
|
"--defaultentrypoints=https",
|
||||||
|
"--defaultentrypoints=ssh",
|
||||||
|
"--providersthrottleduration=4s",
|
||||||
|
}
|
||||||
|
parsers := map[reflect.Type]flaeg.Parser{}
|
||||||
|
var defaultEntryPointsParser DefaultEntryPoints
|
||||||
|
parsers[reflect.TypeOf(DefaultEntryPoints{})] = &defaultEntryPointsParser
|
||||||
|
entryPointsParser := EntryPoints{}
|
||||||
|
parsers[reflect.TypeOf(EntryPoints{})] = &entryPointsParser
|
||||||
|
|
||||||
|
if err := flaeg.LoadWithParsers(&configuration, defaultConfiguration, args, parsers); err != nil {
|
||||||
|
t.Fatalf("Error: %s", err)
|
||||||
|
}
|
||||||
|
// fmt.Printf("result : \n%+v\n", configuration)
|
||||||
|
|
||||||
|
//Check
|
||||||
|
check := *defaultConfiguration
|
||||||
|
check.File = nil
|
||||||
|
check.Web.Address = ":8888"
|
||||||
|
check.AccessLogsFile = "log2/access.log"
|
||||||
|
check.Etcd.TLS.InsecureSkipVerify = true
|
||||||
|
check.EntryPoints = make(map[string]*EntryPoint)
|
||||||
|
check.EntryPoints["http"] = &EntryPoint{
|
||||||
|
Address: ":8000",
|
||||||
|
Redirect: &Redirect{
|
||||||
|
EntryPoint: "https",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
check.EntryPoints["https"] = &EntryPoint{
|
||||||
|
Address: ":8443",
|
||||||
|
Redirect: &Redirect{
|
||||||
|
EntryPoint: "http",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
check.DefaultEntryPoints = []string{"https", "ssh"}
|
||||||
|
check.ProvidersThrottleDuration = time.Duration(4 * time.Second)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(&configuration, &check) {
|
||||||
|
t.Fatalf("\nexpected\t: %+v\ngot\t\t\t: %+v", check, configuration)
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
// BoltDb holds configurations of the BoltDb provider.
|
// BoltDb holds configurations of the BoltDb provider.
|
||||||
type BoltDb struct {
|
type BoltDb struct {
|
||||||
Kv `mapstructure:",squash"`
|
Kv `mapstructure:",squash" description:"go through"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide allows the provider to provide configurations to traefik
|
// Provide allows the provider to provide configurations to traefik
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
// Consul holds configurations of the Consul provider.
|
// Consul holds configurations of the Consul provider.
|
||||||
type Consul struct {
|
type Consul struct {
|
||||||
Kv `mapstructure:",squash"`
|
Kv `mapstructure:",squash" description:"go through"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide allows the provider to provide configurations to traefik
|
// Provide allows the provider to provide configurations to traefik
|
||||||
|
|
|
@ -24,8 +24,8 @@ const (
|
||||||
// ConsulCatalog holds configurations of the Consul catalog provider.
|
// ConsulCatalog holds configurations of the Consul catalog provider.
|
||||||
type ConsulCatalog struct {
|
type ConsulCatalog struct {
|
||||||
BaseProvider `mapstructure:",squash"`
|
BaseProvider `mapstructure:",squash"`
|
||||||
Endpoint string
|
Endpoint string `description:"Consul server endpoint"`
|
||||||
Domain string
|
Domain string `description:"Default domain used"`
|
||||||
client *api.Client
|
client *api.Client
|
||||||
Prefix string
|
Prefix string
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,17 +30,17 @@ const DockerAPIVersion string = "1.21"
|
||||||
// Docker holds configurations of the Docker provider.
|
// Docker holds configurations of the Docker provider.
|
||||||
type Docker struct {
|
type Docker struct {
|
||||||
BaseProvider `mapstructure:",squash"`
|
BaseProvider `mapstructure:",squash"`
|
||||||
Endpoint string
|
Endpoint string `description:"Docker server endpoint. Can be a tcp or a unix socket endpoint"`
|
||||||
Domain string
|
Domain string `description:"Default domain used"`
|
||||||
TLS *DockerTLS
|
TLS *DockerTLS `description:"Enable Docker TLS support"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DockerTLS holds TLS specific configurations
|
// DockerTLS holds TLS specific configurations
|
||||||
type DockerTLS struct {
|
type DockerTLS struct {
|
||||||
CA string
|
CA string `description:"TLS CA"`
|
||||||
Cert string
|
Cert string `description:"TLS cert"`
|
||||||
Key string
|
Key string `description:"TLS key"`
|
||||||
InsecureSkipVerify bool
|
InsecureSkipVerify bool `description:"TLS insecure skip verify"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *Docker) createClient() (client.APIClient, error) {
|
func (provider *Docker) createClient() (client.APIClient, error) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
// Etcd holds configurations of the Etcd provider.
|
// Etcd holds configurations of the Etcd provider.
|
||||||
type Etcd struct {
|
type Etcd struct {
|
||||||
Kv `mapstructure:",squash"`
|
Kv `mapstructure:",squash" description:"go through"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide allows the provider to provide configurations to traefik
|
// Provide allows the provider to provide configurations to traefik
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
// File holds configurations of the File provider.
|
// File holds configurations of the File provider.
|
||||||
type File struct {
|
type File struct {
|
||||||
BaseProvider `mapstructure:",squash"`
|
BaseProvider `mapstructure:",squash" description:"go through"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide allows the provider to provide configurations to traefik
|
// Provide allows the provider to provide configurations to traefik
|
||||||
|
|
|
@ -20,12 +20,15 @@ const (
|
||||||
serviceAccountCACert = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
serviceAccountCACert = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Namespaces holds kubernetes namespaces
|
||||||
|
type Namespaces []string
|
||||||
|
|
||||||
// Kubernetes holds configurations of the Kubernetes provider.
|
// Kubernetes holds configurations of the Kubernetes provider.
|
||||||
type Kubernetes struct {
|
type Kubernetes struct {
|
||||||
BaseProvider `mapstructure:",squash"`
|
BaseProvider `mapstructure:",squash"`
|
||||||
Endpoint string
|
Endpoint string `description:"Kubernetes server endpoint"`
|
||||||
disablePassHostHeaders bool
|
DisablePassHostHeaders bool `description:"Kubernetes disable PassHost Headers"`
|
||||||
Namespaces []string
|
Namespaces Namespaces `description:"Kubernetes namespaces"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *Kubernetes) createClient() (k8s.Client, error) {
|
func (provider *Kubernetes) createClient() (k8s.Client, error) {
|
||||||
|
@ -259,7 +262,7 @@ func equalPorts(servicePort k8s.ServicePort, ingressPort k8s.IntOrString) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *Kubernetes) getPassHostHeader() bool {
|
func (provider *Kubernetes) getPassHostHeader() bool {
|
||||||
if provider.disablePassHostHeaders {
|
if provider.DisablePassHostHeaders {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -22,20 +22,20 @@ import (
|
||||||
|
|
||||||
// Kv holds common configurations of key-value providers.
|
// Kv holds common configurations of key-value providers.
|
||||||
type Kv struct {
|
type Kv struct {
|
||||||
BaseProvider `mapstructure:",squash"`
|
BaseProvider `mapstructure:",squash" description:"go through"`
|
||||||
Endpoint string
|
Endpoint string `description:"Comma sepparated server endpoints"`
|
||||||
Prefix string
|
Prefix string `description:"Prefix used for KV store"`
|
||||||
TLS *KvTLS
|
TLS *KvTLS `description:"Enable TLS support"`
|
||||||
storeType store.Backend
|
storeType store.Backend
|
||||||
kvclient store.Store
|
kvclient store.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
// KvTLS holds TLS specific configurations
|
// KvTLS holds TLS specific configurations
|
||||||
type KvTLS struct {
|
type KvTLS struct {
|
||||||
CA string
|
CA string `description:"TLS CA"`
|
||||||
Cert string
|
Cert string `description:"TLS cert"`
|
||||||
Key string
|
Key string `description:"TLS key"`
|
||||||
InsecureSkipVerify bool
|
InsecureSkipVerify bool `description:"TLS insecure skip verify"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *Kv) watchKv(configurationChan chan<- types.ConfigMessage, prefix string, stop chan bool) error {
|
func (provider *Kv) watchKv(configurationChan chan<- types.ConfigMessage, prefix string, stop chan bool) error {
|
||||||
|
|
|
@ -20,10 +20,10 @@ import (
|
||||||
|
|
||||||
// Marathon holds configuration of the Marathon provider.
|
// Marathon holds configuration of the Marathon provider.
|
||||||
type Marathon struct {
|
type Marathon struct {
|
||||||
BaseProvider `mapstructure:",squash"`
|
BaseProvider `mapstructure:",squash" description:"go through"`
|
||||||
Endpoint string
|
Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon"`
|
||||||
Domain string
|
Domain string `description:"Default domain used"`
|
||||||
ExposedByDefault bool
|
ExposedByDefault bool `description:"Expose Marathon apps by default"`
|
||||||
Basic *MarathonBasic
|
Basic *MarathonBasic
|
||||||
TLS *tls.Config
|
TLS *tls.Config
|
||||||
marathonClient marathon.Marathon
|
marathonClient marathon.Marathon
|
||||||
|
@ -36,8 +36,8 @@ type MarathonBasic struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type lightMarathonClient interface {
|
type lightMarathonClient interface {
|
||||||
Applications(url.Values) (*marathon.Applications, error)
|
|
||||||
AllTasks(v url.Values) (*marathon.Tasks, error)
|
AllTasks(v url.Values) (*marathon.Tasks, error)
|
||||||
|
Applications(url.Values) (*marathon.Applications, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide allows the provider to provide configurations to traefik
|
// Provide allows the provider to provide configurations to traefik
|
||||||
|
|
|
@ -22,8 +22,8 @@ type Provider interface {
|
||||||
|
|
||||||
// BaseProvider should be inherited by providers
|
// BaseProvider should be inherited by providers
|
||||||
type BaseProvider struct {
|
type BaseProvider struct {
|
||||||
Watch bool
|
Watch bool `description:"Watch provider"`
|
||||||
Filename string
|
Filename string `description:"Override default configuration template. For advanced users :)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BaseProvider) getConfiguration(defaultTemplateFile string, funcMap template.FuncMap, templateObjects interface{}) (*types.Configuration, error) {
|
func (p *BaseProvider) getConfiguration(defaultTemplateFile string, funcMap template.FuncMap, templateObjects interface{}) (*types.Configuration, error) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
// Zookepper holds configurations of the Zookepper provider.
|
// Zookepper holds configurations of the Zookepper provider.
|
||||||
type Zookepper struct {
|
type Zookepper struct {
|
||||||
Kv
|
Kv `description:"go through"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide allows the provider to provide configurations to traefik
|
// Provide allows the provider to provide configurations to traefik
|
||||||
|
|
97
traefik.go
97
traefik.go
|
@ -1,16 +1,111 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
"github.com/containous/flaeg"
|
||||||
|
"github.com/containous/staert"
|
||||||
|
"github.com/containous/traefik/middlewares"
|
||||||
fmtlog "log"
|
fmtlog "log"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
if err := traefikCmd.Execute(); err != nil {
|
|
||||||
|
//traefik config inits
|
||||||
|
traefikConfiguration := NewTraefikConfiguration()
|
||||||
|
traefikPointersConfiguration := NewTraefikPointersConfiguration()
|
||||||
|
//traefik Command init
|
||||||
|
traefikCmd := &flaeg.Command{
|
||||||
|
Name: "traefik",
|
||||||
|
Description: `traefik is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.
|
||||||
|
Complete documentation is available at https://traefik.io`,
|
||||||
|
Config: traefikConfiguration,
|
||||||
|
DefaultPointersConfig: traefikPointersConfiguration,
|
||||||
|
Run: func() error {
|
||||||
|
run(traefikConfiguration)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
//version Command init
|
||||||
|
versionCmd := &flaeg.Command{
|
||||||
|
Name: "version",
|
||||||
|
Description: `Print version`,
|
||||||
|
Run: func() error {
|
||||||
|
fmtlog.Println(Version + " built on the " + BuildDate)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
//staert init
|
||||||
|
s := staert.NewStaert(traefikCmd)
|
||||||
|
|
||||||
|
//init toml source
|
||||||
|
toml := staert.NewTomlSource("traefik", []string{traefikConfiguration.ConfigFile, "/etc/traefik/", "$HOME/.traefik/", "."})
|
||||||
|
//init flaeg source
|
||||||
|
f := flaeg.New(traefikCmd, os.Args[1:])
|
||||||
|
//add custom parsers
|
||||||
|
f.AddParser(reflect.TypeOf(EntryPoints{}), &EntryPoints{})
|
||||||
|
f.AddParser(reflect.TypeOf(DefaultEntryPoints{}), &DefaultEntryPoints{})
|
||||||
|
//Wait for DefaultSliceStringParser
|
||||||
|
//add version command
|
||||||
|
f.AddCommand(versionCmd)
|
||||||
|
|
||||||
|
//add sources to staert
|
||||||
|
s.AddSource(f)
|
||||||
|
s.AddSource(toml)
|
||||||
|
s.AddSource(f)
|
||||||
|
if err := s.Run(); err != nil {
|
||||||
fmtlog.Println(err)
|
fmtlog.Println(err)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func run(traefikConfiguration *TraefikConfiguration) {
|
||||||
|
fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags)
|
||||||
|
|
||||||
|
// load global configuration
|
||||||
|
globalConfiguration := traefikConfiguration.GlobalConfiguration
|
||||||
|
|
||||||
|
http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost = globalConfiguration.MaxIdleConnsPerHost
|
||||||
|
loggerMiddleware := middlewares.NewLogger(globalConfiguration.AccessLogsFile)
|
||||||
|
defer loggerMiddleware.Close()
|
||||||
|
|
||||||
|
// logging
|
||||||
|
level, err := log.ParseLevel(strings.ToLower(globalConfiguration.LogLevel))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error getting level", err)
|
||||||
|
}
|
||||||
|
log.SetLevel(level)
|
||||||
|
|
||||||
|
if len(globalConfiguration.TraefikLogsFile) > 0 {
|
||||||
|
fi, err := os.OpenFile(globalConfiguration.TraefikLogsFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
|
defer func() {
|
||||||
|
if err := fi.Close(); err != nil {
|
||||||
|
log.Error("Error closinf file", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error opening file", err)
|
||||||
|
} else {
|
||||||
|
log.SetOutput(fi)
|
||||||
|
log.SetFormatter(&log.TextFormatter{DisableColors: true, FullTimestamp: true, DisableSorting: true})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.SetFormatter(&log.TextFormatter{FullTimestamp: true, DisableSorting: true})
|
||||||
|
}
|
||||||
|
jsonConf, _ := json.Marshal(globalConfiguration)
|
||||||
|
log.Debugf("Global configuration loaded %s", string(jsonConf))
|
||||||
|
server := NewServer(globalConfiguration)
|
||||||
|
server.Start()
|
||||||
|
defer server.Close()
|
||||||
|
log.Info("Shutting down")
|
||||||
|
}
|
||||||
|
|
9
web.go
9
web.go
|
@ -23,10 +23,11 @@ var metrics = stats.New()
|
||||||
// WebProvider is a provider.Provider implementation that provides the UI.
|
// WebProvider is a provider.Provider implementation that provides the UI.
|
||||||
// FIXME to be handled another way.
|
// FIXME to be handled another way.
|
||||||
type WebProvider struct {
|
type WebProvider struct {
|
||||||
Address string
|
Address string `description:"Web administration port"`
|
||||||
CertFile, KeyFile string
|
CertFile string `description:"SSL certificate"`
|
||||||
ReadOnly bool
|
KeyFile string `description:"SSL certificate"`
|
||||||
server *Server
|
ReadOnly bool `description:"Enable read only API"`
|
||||||
|
server *Server
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
Loading…
Reference in a new issue