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"
2016-03-21 13:10:18 +03:00
"github.com/containous/traefik/acme"
2016-02-24 18:43:39 +03:00
"github.com/containous/traefik/provider"
"github.com/containous/traefik/types"
2016-05-03 17:52:14 +03:00
"regexp"
"strings"
"time"
2015-09-25 12:44:19 +03:00
)
2016-05-03 17:52:14 +03:00
// TraefikConfiguration holds GlobalConfiguration and other stuff
type TraefikConfiguration struct {
GlobalConfiguration
2016-05-30 12:37:12 +03:00
ConfigFile string ` short:"c" description:"Configuration file to use (TOML)." `
2016-05-03 17:52:14 +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 {
2016-05-25 18:06:34 +03:00
GraceTimeOut int64 ` short:"g" description:"Configuration file to use (TOML)." `
2016-05-26 16:55:50 +03:00
Debug bool ` short:"d" description:"Enable debug mode" `
2016-05-25 18:06:34 +03:00
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'" `
2016-06-02 16:17:04 +03:00
Constraints types . Constraints ` description:"Filter services by constraint, matching with service tags." `
2016-05-25 18:06:34 +03:00
ACME * acme . ACME ` description:"Enable ACME (Let's Encrypt): automatic SSL" `
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 ` description:"Enable retry sending request if network error" `
2016-05-03 17:52:14 +03:00
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" `
2016-07-20 12:56:14 +03:00
Mesos * provider . Mesos ` description:"Enable Mesos backend" `
2015-09-10 16:13:35 +03:00
}
2016-01-29 22:34:17 +03:00
// DefaultEntryPoints holds default entry points
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 {
2016-05-27 12:13:34 +03:00
return strings . Join ( * dep , "," )
2016-01-29 22:34:17 +03:00
}
// 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 ( dep * DefaultEntryPoints ) Set ( value string ) error {
entrypoints := strings . Split ( value , "," )
if len ( entrypoints ) == 0 {
return errors . New ( "Bad DefaultEntryPoints format: " + value )
}
for _ , entrypoint := range entrypoints {
* dep = append ( * dep , entrypoint )
}
return nil
}
2016-05-03 17:52:14 +03:00
// 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 ) )
}
2016-01-29 22:34:17 +03:00
// Type is type of the struct
func ( dep * DefaultEntryPoints ) Type ( ) string {
2016-05-24 15:58:25 +03:00
return fmt . Sprint ( "defaultentrypoints" )
2016-01-29 22:34:17 +03:00
}
// EntryPoints holds entry points configuration of the reverse proxy (ip, port, TLS...)
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 {
2016-05-25 18:06:34 +03:00
return fmt . Sprintf ( "%+v" , * ep )
2016-01-29 22:34:17 +03:00
}
// 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 ( ep * EntryPoints ) Set ( value string ) error {
2016-07-05 11:54:58 +03:00
regex := regexp . MustCompile ( "(?:Name:(?P<Name>\\S*))\\s*(?:Address:(?P<Address>\\S*))?\\s*(?:TLS:(?P<TLS>\\S*))?\\s*((?P<TLSACME>TLS))?\\s*(?:Redirect.EntryPoint:(?P<RedirectEntryPoint>\\S*))?\\s*(?:Redirect.Regex:(?P<RedirectRegex>\\S*))?\\s*(?:Redirect.Replacement:(?P<RedirectReplacement>\\S*))?" )
2016-01-29 22:34:17 +03:00
match := regex . FindAllStringSubmatch ( value , - 1 )
if match == nil {
return errors . New ( "Bad EntryPoints format: " + value )
}
matchResult := match [ 0 ]
result := make ( map [ string ] string )
for i , name := range regex . SubexpNames ( ) {
if i != 0 {
result [ name ] = matchResult [ i ]
}
}
var tls * TLS
if len ( result [ "TLS" ] ) > 0 {
certs := Certificates { }
2016-03-22 03:32:02 +03:00
if err := certs . Set ( result [ "TLS" ] ) ; err != nil {
return err
}
2016-01-29 22:34:17 +03:00
tls = & TLS {
Certificates : certs ,
}
2016-07-05 11:54:58 +03:00
} else if len ( result [ "TLSACME" ] ) > 0 {
tls = & TLS {
Certificates : Certificates { } ,
}
2016-01-29 22:34:17 +03:00
}
var redirect * Redirect
if len ( result [ "RedirectEntryPoint" ] ) > 0 || len ( result [ "RedirectRegex" ] ) > 0 || len ( result [ "RedirectReplacement" ] ) > 0 {
redirect = & Redirect {
EntryPoint : result [ "RedirectEntryPoint" ] ,
Regex : result [ "RedirectRegex" ] ,
Replacement : result [ "RedirectReplacement" ] ,
}
}
( * ep ) [ result [ "Name" ] ] = & EntryPoint {
Address : result [ "Address" ] ,
TLS : tls ,
Redirect : redirect ,
}
return nil
}
2016-05-03 17:52:14 +03:00
// 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 ) )
}
2016-01-29 22:34:17 +03:00
// Type is type of the struct
func ( ep * EntryPoints ) Type ( ) string {
2016-06-02 16:17:04 +03:00
return fmt . Sprint ( "entrypoints" )
2016-05-31 10:54:42 +03:00
}
2016-01-29 22:34:17 +03:00
// EntryPoint holds an entry point configuration of the reverse proxy (ip, port, TLS...)
type EntryPoint struct {
Network string
Address string
TLS * TLS
Redirect * Redirect
}
// Redirect configures a redirection of an entry point to another, or to an URL
type Redirect struct {
EntryPoint string
Regex string
Replacement string
}
// TLS configures TLS for an entry point
type TLS struct {
Certificates Certificates
}
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
}
2016-03-29 23:25:32 +03:00
// Retry contains request retry config
type Retry struct {
2016-06-15 20:07:33 +03:00
Attempts int ` description:"Number of attempts" `
2016-03-29 23:25:32 +03:00
}
2016-05-25 18:06:34 +03:00
// NewTraefikDefaultPointersConfiguration creates a TraefikConfiguration with pointers default values
func NewTraefikDefaultPointersConfiguration ( ) * TraefikConfiguration {
2016-05-03 17:52:14 +03:00
//default Docker
var defaultDocker provider . Docker
defaultDocker . Watch = true
2016-07-14 12:32:15 +03:00
defaultDocker . ExposedByDefault = true
2016-05-03 17:52:14 +03:00
defaultDocker . Endpoint = "unix:///var/run/docker.sock"
// 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
2016-05-31 10:54:42 +03:00
defaultMarathon . Constraints = [ ] types . Constraint { }
2016-05-03 17:52:14 +03:00
// default Consul
var defaultConsul provider . Consul
defaultConsul . Watch = true
defaultConsul . Endpoint = "127.0.0.1:8500"
2016-06-10 00:44:49 +03:00
defaultConsul . Prefix = "traefik"
2016-05-31 10:54:42 +03:00
defaultConsul . Constraints = [ ] types . Constraint { }
2016-05-03 17:52:14 +03:00
// default ConsulCatalog
var defaultConsulCatalog provider . ConsulCatalog
defaultConsulCatalog . Endpoint = "127.0.0.1:8500"
2016-05-31 10:54:42 +03:00
defaultConsulCatalog . Constraints = [ ] types . Constraint { }
2016-05-03 17:52:14 +03:00
// default Etcd
var defaultEtcd provider . Etcd
defaultEtcd . Watch = true
defaultEtcd . Endpoint = "127.0.0.1:400"
defaultEtcd . Prefix = "/traefik"
2016-05-31 10:54:42 +03:00
defaultEtcd . Constraints = [ ] types . Constraint { }
2016-05-03 17:52:14 +03:00
//default Zookeeper
var defaultZookeeper provider . Zookepper
defaultZookeeper . Watch = true
defaultZookeeper . Endpoint = "127.0.0.1:2181"
defaultZookeeper . Prefix = "/traefik"
2016-05-31 10:54:42 +03:00
defaultZookeeper . Constraints = [ ] types . Constraint { }
2016-05-03 17:52:14 +03:00
//default Boltdb
var defaultBoltDb provider . BoltDb
defaultBoltDb . Watch = true
defaultBoltDb . Endpoint = "127.0.0.1:4001"
defaultBoltDb . Prefix = "/traefik"
2016-05-31 10:54:42 +03:00
defaultBoltDb . Constraints = [ ] types . Constraint { }
2016-05-03 17:52:14 +03:00
//default Kubernetes
var defaultKubernetes provider . Kubernetes
defaultKubernetes . Watch = true
2016-07-11 22:39:20 +03:00
defaultKubernetes . Endpoint = ""
2016-07-12 08:25:01 +03:00
defaultKubernetes . LabelSelector = ""
2016-05-31 10:54:42 +03:00
defaultKubernetes . Constraints = [ ] types . Constraint { }
2016-05-03 17:52:14 +03:00
2016-07-20 12:56:14 +03:00
// default Mesos
var defaultMesos provider . Mesos
defaultMesos . Watch = true
defaultMesos . Endpoint = "http://127.0.0.1:5050"
defaultMesos . ExposedByDefault = true
defaultMesos . Constraints = [ ] types . Constraint { }
2016-05-03 17:52:14 +03:00
defaultConfiguration := GlobalConfiguration {
Docker : & defaultDocker ,
File : & defaultFile ,
Web : & defaultWeb ,
Marathon : & defaultMarathon ,
Consul : & defaultConsul ,
ConsulCatalog : & defaultConsulCatalog ,
Etcd : & defaultEtcd ,
Zookeeper : & defaultZookeeper ,
Boltdb : & defaultBoltDb ,
Kubernetes : & defaultKubernetes ,
2016-07-20 12:56:14 +03:00
Mesos : & defaultMesos ,
2016-06-15 20:07:33 +03:00
Retry : & Retry { } ,
2016-05-03 17:52:14 +03:00
}
return & TraefikConfiguration {
GlobalConfiguration : defaultConfiguration ,
2016-01-29 22:34:17 +03:00
}
2015-11-06 20:11:57 +03:00
}
2016-05-03 17:52:14 +03:00
// NewTraefikConfiguration creates a TraefikConfiguration with default values
func NewTraefikConfiguration ( ) * TraefikConfiguration {
return & TraefikConfiguration {
GlobalConfiguration : GlobalConfiguration {
GraceTimeOut : 10 ,
2016-05-19 18:12:36 +03:00
AccessLogsFile : "" ,
TraefikLogsFile : "" ,
2016-05-03 17:52:14 +03:00
LogLevel : "ERROR" ,
2016-05-24 15:58:25 +03:00
EntryPoints : map [ string ] * EntryPoint { } ,
2016-05-31 10:54:42 +03:00
Constraints : [ ] types . Constraint { } ,
2016-05-24 15:58:25 +03:00
DefaultEntryPoints : [ ] string { } ,
2016-05-03 17:52:14 +03:00
ProvidersThrottleDuration : time . Duration ( 2 * time . Second ) ,
MaxIdleConnsPerHost : 200 ,
} ,
ConfigFile : "" ,
2016-01-14 00:46:44 +03:00
}
}
2015-11-01 18:35:01 +03:00
type configs map [ string ] * types . Configuration