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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
fmtlog "log"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containous/traefik/acme"
|
||||
"github.com/containous/traefik/provider"
|
||||
"github.com/containous/traefik/types"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/spf13/viper"
|
||||
"regexp"
|
||||
"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.).
|
||||
// It's populated from the traefik configuration file passed as an argument to the binary.
|
||||
type GlobalConfiguration struct {
|
||||
GraceTimeOut int64
|
||||
GraceTimeOut int64 `short:"g" description:"Configuration file to use (TOML)."`
|
||||
Debug bool
|
||||
AccessLogsFile string
|
||||
TraefikLogsFile string
|
||||
LogLevel string
|
||||
EntryPoints EntryPoints
|
||||
AccessLogsFile string `description:"Access logs file"`
|
||||
TraefikLogsFile string `description:"Traefik logs file"`
|
||||
LogLevel string `short:"l" description:"Log level"`
|
||||
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
|
||||
DefaultEntryPoints DefaultEntryPoints
|
||||
ProvidersThrottleDuration time.Duration
|
||||
MaxIdleConnsPerHost int
|
||||
DefaultEntryPoints DefaultEntryPoints `description:"Entrypoints to be used by frontends that do not specify any entrypoint"`
|
||||
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 `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used"`
|
||||
Retry *Retry
|
||||
Docker *provider.Docker
|
||||
File *provider.File
|
||||
Web *WebProvider
|
||||
Marathon *provider.Marathon
|
||||
Consul *provider.Consul
|
||||
ConsulCatalog *provider.ConsulCatalog
|
||||
Etcd *provider.Etcd
|
||||
Zookeeper *provider.Zookepper
|
||||
Boltdb *provider.BoltDb
|
||||
Kubernetes *provider.Kubernetes
|
||||
Docker *provider.Docker `description:"Enable Docker backend"`
|
||||
File *provider.File `description:"Enable File backend"`
|
||||
Web *WebProvider `description:"Enable Web backend"`
|
||||
Marathon *provider.Marathon `description:"Enable Marathon backend"`
|
||||
Consul *provider.Consul `description:"Enable Consul backend"`
|
||||
ConsulCatalog *provider.ConsulCatalog `description:"Enable Consul catalog backend"`
|
||||
Etcd *provider.Etcd `description:"Enable Etcd backend"`
|
||||
Zookeeper *provider.Zookepper `description:"Enable Zookeeper backend"`
|
||||
Boltdb *provider.BoltDb `description:"Enable Boltdb backend"`
|
||||
Kubernetes *provider.Kubernetes `description:"Enable Kubernetes backend"`
|
||||
}
|
||||
|
||||
// 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.
|
||||
// The String method's output will be used in diagnostics.
|
||||
func (dep *DefaultEntryPoints) String() string {
|
||||
//TODO :
|
||||
return fmt.Sprintf("%#v", dep)
|
||||
}
|
||||
|
||||
|
@ -64,6 +67,14 @@ func (dep *DefaultEntryPoints) Set(value string) error {
|
|||
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
|
||||
func (dep *DefaultEntryPoints) Type() string {
|
||||
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.
|
||||
// The String method's output will be used in diagnostics.
|
||||
func (ep *EntryPoints) String() string {
|
||||
//TODO :
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -122,6 +134,14 @@ func (ep *EntryPoints) Set(value string) error {
|
|||
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
|
||||
func (ep *EntryPoints) Type() string {
|
||||
return fmt.Sprint("entrypoints²")
|
||||
|
@ -154,6 +174,7 @@ type Certificates []Certificate
|
|||
// The String method's output will be used in diagnostics.
|
||||
func (certs *Certificates) String() string {
|
||||
if len(*certs) == 0 {
|
||||
//TODO :
|
||||
return ""
|
||||
}
|
||||
return (*certs)[0].CertFile + "," + (*certs)[0].KeyFile
|
||||
|
@ -191,117 +212,96 @@ type Retry struct {
|
|||
MaxMem int64
|
||||
}
|
||||
|
||||
// NewGlobalConfiguration returns a GlobalConfiguration with default values.
|
||||
func NewGlobalConfiguration() *GlobalConfiguration {
|
||||
return new(GlobalConfiguration)
|
||||
// NewTraefikPointersConfiguration creates a TraefikConfiguration with pointers default values
|
||||
func NewTraefikPointersConfiguration() *TraefikConfiguration {
|
||||
//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.
|
||||
func LoadConfiguration() *GlobalConfiguration {
|
||||
configuration := NewGlobalConfiguration()
|
||||
viper.SetEnvPrefix("traefik")
|
||||
viper.SetConfigType("toml")
|
||||
viper.AutomaticEnv()
|
||||
if len(viper.GetString("configFile")) > 0 {
|
||||
viper.SetConfigFile(viper.GetString("configFile"))
|
||||
} else {
|
||||
viper.SetConfigName("traefik") // name of config file (without extension)
|
||||
// NewTraefikConfiguration creates a TraefikConfiguration with default values
|
||||
func NewTraefikConfiguration() *TraefikConfiguration {
|
||||
return &TraefikConfiguration{
|
||||
GlobalConfiguration: GlobalConfiguration{
|
||||
GraceTimeOut: 10,
|
||||
AccessLogsFile: "log/access.log",
|
||||
TraefikLogsFile: "log/traefik.log",
|
||||
LogLevel: "ERROR",
|
||||
EntryPoints: map[string]*EntryPoint{"http": &EntryPoint{Address: ":80"}},
|
||||
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
|
||||
|
|
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.
|
||||
type BoltDb struct {
|
||||
Kv `mapstructure:",squash"`
|
||||
Kv `mapstructure:",squash" description:"go through"`
|
||||
}
|
||||
|
||||
// Provide allows the provider to provide configurations to traefik
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
// Consul holds configurations of the Consul provider.
|
||||
type Consul struct {
|
||||
Kv `mapstructure:",squash"`
|
||||
Kv `mapstructure:",squash" description:"go through"`
|
||||
}
|
||||
|
||||
// Provide allows the provider to provide configurations to traefik
|
||||
|
|
|
@ -24,8 +24,8 @@ const (
|
|||
// ConsulCatalog holds configurations of the Consul catalog provider.
|
||||
type ConsulCatalog struct {
|
||||
BaseProvider `mapstructure:",squash"`
|
||||
Endpoint string
|
||||
Domain string
|
||||
Endpoint string `description:"Consul server endpoint"`
|
||||
Domain string `description:"Default domain used"`
|
||||
client *api.Client
|
||||
Prefix string
|
||||
}
|
||||
|
|
|
@ -30,17 +30,17 @@ const DockerAPIVersion string = "1.21"
|
|||
// Docker holds configurations of the Docker provider.
|
||||
type Docker struct {
|
||||
BaseProvider `mapstructure:",squash"`
|
||||
Endpoint string
|
||||
Domain string
|
||||
TLS *DockerTLS
|
||||
Endpoint string `description:"Docker server endpoint. Can be a tcp or a unix socket endpoint"`
|
||||
Domain string `description:"Default domain used"`
|
||||
TLS *DockerTLS `description:"Enable Docker TLS support"`
|
||||
}
|
||||
|
||||
// DockerTLS holds TLS specific configurations
|
||||
type DockerTLS struct {
|
||||
CA string
|
||||
Cert string
|
||||
Key string
|
||||
InsecureSkipVerify bool
|
||||
CA string `description:"TLS CA"`
|
||||
Cert string `description:"TLS cert"`
|
||||
Key string `description:"TLS key"`
|
||||
InsecureSkipVerify bool `description:"TLS insecure skip verify"`
|
||||
}
|
||||
|
||||
func (provider *Docker) createClient() (client.APIClient, error) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
// Etcd holds configurations of the Etcd provider.
|
||||
type Etcd struct {
|
||||
Kv `mapstructure:",squash"`
|
||||
Kv `mapstructure:",squash" description:"go through"`
|
||||
}
|
||||
|
||||
// Provide allows the provider to provide configurations to traefik
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
|
||||
// File holds configurations of the File provider.
|
||||
type File struct {
|
||||
BaseProvider `mapstructure:",squash"`
|
||||
BaseProvider `mapstructure:",squash" description:"go through"`
|
||||
}
|
||||
|
||||
// Provide allows the provider to provide configurations to traefik
|
||||
|
|
|
@ -20,12 +20,15 @@ const (
|
|||
serviceAccountCACert = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
||||
)
|
||||
|
||||
// Namespaces holds kubernetes namespaces
|
||||
type Namespaces []string
|
||||
|
||||
// Kubernetes holds configurations of the Kubernetes provider.
|
||||
type Kubernetes struct {
|
||||
BaseProvider `mapstructure:",squash"`
|
||||
Endpoint string
|
||||
disablePassHostHeaders bool
|
||||
Namespaces []string
|
||||
Endpoint string `description:"Kubernetes server endpoint"`
|
||||
DisablePassHostHeaders bool `description:"Kubernetes disable PassHost Headers"`
|
||||
Namespaces Namespaces `description:"Kubernetes namespaces"`
|
||||
}
|
||||
|
||||
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 {
|
||||
if provider.disablePassHostHeaders {
|
||||
if provider.DisablePassHostHeaders {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -22,20 +22,20 @@ import (
|
|||
|
||||
// Kv holds common configurations of key-value providers.
|
||||
type Kv struct {
|
||||
BaseProvider `mapstructure:",squash"`
|
||||
Endpoint string
|
||||
Prefix string
|
||||
TLS *KvTLS
|
||||
BaseProvider `mapstructure:",squash" description:"go through"`
|
||||
Endpoint string `description:"Comma sepparated server endpoints"`
|
||||
Prefix string `description:"Prefix used for KV store"`
|
||||
TLS *KvTLS `description:"Enable TLS support"`
|
||||
storeType store.Backend
|
||||
kvclient store.Store
|
||||
}
|
||||
|
||||
// KvTLS holds TLS specific configurations
|
||||
type KvTLS struct {
|
||||
CA string
|
||||
Cert string
|
||||
Key string
|
||||
InsecureSkipVerify bool
|
||||
CA string `description:"TLS CA"`
|
||||
Cert string `description:"TLS cert"`
|
||||
Key string `description:"TLS key"`
|
||||
InsecureSkipVerify bool `description:"TLS insecure skip verify"`
|
||||
}
|
||||
|
||||
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.
|
||||
type Marathon struct {
|
||||
BaseProvider `mapstructure:",squash"`
|
||||
Endpoint string
|
||||
Domain string
|
||||
ExposedByDefault bool
|
||||
BaseProvider `mapstructure:",squash" description:"go through"`
|
||||
Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon"`
|
||||
Domain string `description:"Default domain used"`
|
||||
ExposedByDefault bool `description:"Expose Marathon apps by default"`
|
||||
Basic *MarathonBasic
|
||||
TLS *tls.Config
|
||||
marathonClient marathon.Marathon
|
||||
|
@ -36,8 +36,8 @@ type MarathonBasic struct {
|
|||
}
|
||||
|
||||
type lightMarathonClient interface {
|
||||
Applications(url.Values) (*marathon.Applications, error)
|
||||
AllTasks(v url.Values) (*marathon.Tasks, error)
|
||||
Applications(url.Values) (*marathon.Applications, error)
|
||||
}
|
||||
|
||||
// Provide allows the provider to provide configurations to traefik
|
||||
|
|
|
@ -22,8 +22,8 @@ type Provider interface {
|
|||
|
||||
// BaseProvider should be inherited by providers
|
||||
type BaseProvider struct {
|
||||
Watch bool
|
||||
Filename string
|
||||
Watch bool `description:"Watch provider"`
|
||||
Filename string `description:"Override default configuration template. For advanced users :)"`
|
||||
}
|
||||
|
||||
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.
|
||||
type Zookepper struct {
|
||||
Kv
|
||||
Kv `description:"go through"`
|
||||
}
|
||||
|
||||
// Provide allows the provider to provide configurations to traefik
|
||||
|
|
97
traefik.go
97
traefik.go
|
@ -1,16 +1,111 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/containous/flaeg"
|
||||
"github.com/containous/staert"
|
||||
"github.com/containous/traefik/middlewares"
|
||||
fmtlog "log"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
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)
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
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.
|
||||
// FIXME to be handled another way.
|
||||
type WebProvider struct {
|
||||
Address string
|
||||
CertFile, KeyFile string
|
||||
ReadOnly bool
|
||||
server *Server
|
||||
Address string `description:"Web administration port"`
|
||||
CertFile string `description:"SSL certificate"`
|
||||
KeyFile string `description:"SSL certificate"`
|
||||
ReadOnly bool `description:"Enable read only API"`
|
||||
server *Server
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
Loading…
Reference in a new issue