forked from SW/traefik
Compare commits
6 Commits
v1.0.alpha
...
v1.0.alpha
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1604786285 | ||
|
|
35cb9100cd | ||
|
|
4729e3e999 | ||
|
|
b0e66a4aa6 | ||
|
|
4218467ab3 | ||
|
|
6e62625ebf |
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/docker/libkv"
|
||||
"github.com/docker/libkv/store"
|
||||
"github.com/emilevauge/traefik/types"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Kv holds common configurations of key-value providers.
|
||||
@@ -73,9 +74,10 @@ func (provider *Kv) loadConfig() *types.Configuration {
|
||||
provider.Prefix,
|
||||
}
|
||||
var KvFuncMap = template.FuncMap{
|
||||
"List": provider.list,
|
||||
"Get": provider.get,
|
||||
"Last": provider.last,
|
||||
"List": provider.list,
|
||||
"Get": provider.get,
|
||||
"GetBool": provider.getBool,
|
||||
"Last": provider.last,
|
||||
}
|
||||
|
||||
configuration, err := provider.getConfiguration("templates/kv.tmpl", KvFuncMap, templateObjects)
|
||||
@@ -104,7 +106,7 @@ func (provider *Kv) get(keys ...string) string {
|
||||
joinedKeys := strings.Join(keys, "")
|
||||
keyPair, err := provider.kvclient.Get(joinedKeys)
|
||||
if err != nil {
|
||||
log.Debug("Error getting key: ", joinedKeys, err)
|
||||
log.Error("Error getting key: ", joinedKeys, err)
|
||||
return ""
|
||||
} else if keyPair == nil {
|
||||
return ""
|
||||
@@ -112,6 +114,16 @@ func (provider *Kv) get(keys ...string) string {
|
||||
return string(keyPair.Value)
|
||||
}
|
||||
|
||||
func (provider *Kv) getBool(keys ...string) bool {
|
||||
value := provider.get(keys...)
|
||||
b, err := strconv.ParseBool(string(value))
|
||||
if err != nil {
|
||||
log.Error("Error getting key: ", strings.Join(keys, ""), err)
|
||||
return false
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (provider *Kv) last(key string) string {
|
||||
splittedKey := strings.Split(key, "/")
|
||||
return splittedKey[len(splittedKey)-1]
|
||||
|
||||
@@ -194,6 +194,61 @@ func TestKvGet(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestKvGetBool(t *testing.T) {
|
||||
cases := []struct {
|
||||
provider *Kv
|
||||
keys []string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
provider: &Kv{
|
||||
kvclient: &Mock{
|
||||
KVPairs: []*store.KVPair{
|
||||
{
|
||||
Key: "foo",
|
||||
Value: []byte("true"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
keys: []string{"foo"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
provider: &Kv{
|
||||
kvclient: &Mock{
|
||||
KVPairs: []*store.KVPair{
|
||||
{
|
||||
Key: "foo",
|
||||
Value: []byte("false"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
keys: []string{"foo"},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
actual := c.provider.getBool(c.keys...)
|
||||
if actual != c.expected {
|
||||
t.Fatalf("expected %v, got %v for %v and %v", c.expected, actual, c.keys, c.provider)
|
||||
}
|
||||
}
|
||||
|
||||
// Error case
|
||||
provider := &Kv{
|
||||
kvclient: &Mock{
|
||||
Error: true,
|
||||
},
|
||||
}
|
||||
actual := provider.get("anything")
|
||||
if actual != "" {
|
||||
t.Fatalf("Should have return nil, got %v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKvLast(t *testing.T) {
|
||||
cases := []struct {
|
||||
key string
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
{{$frontend := Last .}}
|
||||
[frontends.{{$frontend}}]
|
||||
backend = "{{Get . "/backend"}}"
|
||||
passHostHeader = "{{Get . "/passHostHeader"}}"
|
||||
passHostHeader = "{{GetBool . "/passHostHeader"}}"
|
||||
{{$routes := List . "/routes/"}}
|
||||
{{range $routes}}
|
||||
[frontends.{{$frontend}}.routes.{{Last .}}]
|
||||
|
||||
19
traefik.go
19
traefik.go
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/mailgun/oxy/roundrobin"
|
||||
"github.com/thoas/stats"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -53,6 +54,7 @@ func main() {
|
||||
defer close(stopChan)
|
||||
var providers = []provider.Provider{}
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
var serverLock sync.Mutex
|
||||
|
||||
// load global configuration
|
||||
globalConfiguration := LoadFileConfig(*globalConfigFile)
|
||||
@@ -124,6 +126,7 @@ func main() {
|
||||
|
||||
newConfigurationRouter, err := LoadConfig(newConfigurations, globalConfiguration)
|
||||
if err == nil {
|
||||
serverLock.Lock()
|
||||
currentConfigurations = newConfigurations
|
||||
configurationRouter = newConfigurationRouter
|
||||
oldServer := srv
|
||||
@@ -138,6 +141,7 @@ func main() {
|
||||
log.Info("Stopping old server")
|
||||
oldServer.Close()
|
||||
}
|
||||
serverLock.Unlock()
|
||||
} else {
|
||||
log.Error("Error loading new configuration, aborted ", err)
|
||||
}
|
||||
@@ -199,11 +203,13 @@ func main() {
|
||||
//negroni.Use(middlewares.NewRoutes(configurationRouter))
|
||||
|
||||
var er error
|
||||
serverLock.Lock()
|
||||
srv, er = prepareServer(configurationRouter, globalConfiguration, nil, loggerMiddleware, metrics)
|
||||
if er != nil {
|
||||
log.Fatal("Error preparing server: ", er)
|
||||
}
|
||||
go startServer(srv, globalConfiguration)
|
||||
serverLock.Unlock()
|
||||
|
||||
<-stopChan
|
||||
log.Info("Shutting down")
|
||||
@@ -290,7 +296,10 @@ func LoadConfig(configurations configs, globalConfiguration *GlobalConfiguration
|
||||
newRoute := router.NewRoute().Name(frontendName)
|
||||
for routeName, route := range frontend.Routes {
|
||||
log.Debugf("Creating route %s %s:%s", routeName, route.Rule, route.Value)
|
||||
newRouteReflect := Invoke(newRoute, route.Rule, route.Value)
|
||||
newRouteReflect, err := invoke(newRoute, route.Rule, route.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newRoute = newRouteReflect[0].Interface().(*mux.Route)
|
||||
}
|
||||
if backends[frontend.Backend] == nil {
|
||||
@@ -354,10 +363,14 @@ func LoadConfig(configurations configs, globalConfiguration *GlobalConfiguration
|
||||
|
||||
// Invoke calls the specified method with the specified arguments on the specified interface.
|
||||
// It uses the go(lang) reflect package.
|
||||
func Invoke(any interface{}, name string, args ...interface{}) []reflect.Value {
|
||||
func invoke(any interface{}, name string, args ...interface{}) ([]reflect.Value, error) {
|
||||
inputs := make([]reflect.Value, len(args))
|
||||
for i := range args {
|
||||
inputs[i] = reflect.ValueOf(args[i])
|
||||
}
|
||||
return reflect.ValueOf(any).MethodByName(name).Call(inputs)
|
||||
method := reflect.ValueOf(any).MethodByName(name)
|
||||
if method.IsValid() {
|
||||
return method.Call(inputs), nil
|
||||
}
|
||||
return nil, errors.New("Method not found: " + name)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user