2015-09-07 11:38:58 +03:00
package main
2015-09-25 12:44:19 +03:00
import (
2016-01-23 19:41:56 +03:00
"errors"
"fmt"
2015-11-06 20:11:57 +03:00
fmtlog "log"
2016-01-23 19:41:56 +03:00
"strings"
2015-10-08 18:56:45 +03:00
"time"
2015-11-01 18:35:01 +03:00
"github.com/emilevauge/traefik/provider"
"github.com/emilevauge/traefik/types"
2016-01-14 00:46:44 +03:00
"github.com/mitchellh/mapstructure"
"github.com/spf13/viper"
2015-09-25 12:44:19 +03:00
)
2015-11-06 20:11:57 +03:00
// GlobalConfiguration holds global configuration (with providers, etc.).
// It's populated from the traefik configuration file passed as an argument to the binary.
2015-09-10 16:13:35 +03:00
type GlobalConfiguration struct {
2015-10-17 15:14:20 +03:00
Port string
GraceTimeOut int64
AccessLogsFile string
TraefikLogsFile string
2016-01-14 00:46:44 +03:00
Certificates Certificates
2015-10-17 15:14:20 +03:00
LogLevel string
ProvidersThrottleDuration time . Duration
2015-11-02 21:48:34 +03:00
Docker * provider . Docker
File * provider . File
2015-10-17 15:14:20 +03:00
Web * WebProvider
2015-11-02 21:48:34 +03:00
Marathon * provider . Marathon
Consul * provider . Consul
Etcd * provider . Etcd
Zookeeper * provider . Zookepper
Boltdb * provider . BoltDb
2015-09-10 16:13:35 +03:00
}
2016-01-14 00:46:44 +03:00
// Certificates defines traefik certificates type
type Certificates [ ] Certificate
// 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 ( certs * Certificates ) String ( ) string {
if len ( * certs ) == 0 {
return ""
}
return ( * certs ) [ 0 ] . CertFile + "," + ( * certs ) [ 0 ] . KeyFile
}
// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func ( certs * Certificates ) Set ( value string ) error {
files := strings . Split ( value , "," )
if len ( files ) != 2 {
return errors . New ( "Bad certificates format: " + value )
}
* certs = append ( * certs , Certificate {
CertFile : files [ 0 ] ,
KeyFile : files [ 1 ] ,
} )
return nil
}
// Type is type of the struct
func ( certs * Certificates ) Type ( ) string {
return fmt . Sprint ( "certificates" )
}
2015-11-21 04:59:49 +03:00
// Certificate holds a SSL cert/key pair
type Certificate struct {
CertFile string
KeyFile string
}
2015-11-06 20:11:57 +03:00
// NewGlobalConfiguration returns a GlobalConfiguration with default values.
2015-09-10 16:13:35 +03:00
func NewGlobalConfiguration ( ) * GlobalConfiguration {
globalConfiguration := new ( GlobalConfiguration )
// default values
2015-09-14 15:38:21 +03:00
globalConfiguration . Port = ":80"
2015-09-10 16:13:35 +03:00
globalConfiguration . GraceTimeOut = 10
2015-09-11 17:40:54 +03:00
globalConfiguration . LogLevel = "ERROR"
2015-10-17 15:14:20 +03:00
globalConfiguration . ProvidersThrottleDuration = time . Duration ( 2 * time . Second )
2015-09-10 16:13:35 +03:00
return globalConfiguration
}
2015-09-07 11:38:58 +03:00
2016-01-14 00:46:44 +03:00
// LoadConfiguration returns a GlobalConfiguration.
func LoadConfiguration ( ) * GlobalConfiguration {
2015-11-06 20:11:57 +03:00
configuration := NewGlobalConfiguration ( )
2016-01-14 00:46:44 +03:00
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)
}
2016-01-22 14:36:24 +03:00
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
2016-01-23 19:41:56 +03:00
if err := viper . ReadInConfig ( ) ; err != nil {
2016-01-14 00:46:44 +03:00
fmtlog . Fatalf ( "Error reading file: %s" , err )
}
if len ( arguments . Certificates ) > 0 {
viper . Set ( "certificates" , arguments . Certificates )
}
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 . consul {
viper . Set ( "consul" , arguments . Consul )
}
if arguments . zookeeper {
viper . Set ( "zookeeper" , arguments . Zookeeper )
}
if arguments . etcd {
viper . Set ( "etcd" , arguments . Etcd )
}
if arguments . boltdb {
viper . Set ( "boltdb" , arguments . Boltdb )
}
2016-01-23 19:41:56 +03:00
if err := unmarshal ( & configuration ) ; err != nil {
2015-11-06 20:11:57 +03:00
fmtlog . Fatalf ( "Error reading file: %s" , err )
}
2016-01-14 00:46:44 +03:00
2015-11-06 20:11:57 +03:00
return configuration
}
2016-01-14 00:46:44 +03:00
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
}
2015-11-01 18:35:01 +03:00
type configs map [ string ] * types . Configuration