Compare commits

...

6 Commits

Author SHA1 Message Date
Vincent Demeester
1604786285 Merge pull request #126 from emilevauge/lock-prepareserver
Add mutex around prepareserver
2015-11-24 10:20:44 +01:00
emile
35cb9100cd Add mutex around prepareserver 2015-11-24 09:12:20 +01:00
Vincent Demeester
4729e3e999 Merge pull request #124 from emilevauge/panic-bad-configuration
Add check in invoked method
2015-11-23 20:54:16 +01:00
emile
b0e66a4aa6 Add check invoked method 2015-11-23 16:06:47 +01:00
Vincent Demeester
4218467ab3 Merge pull request #122 from emilevauge/add-getBool-kvprovider
Add GetBool function in KV provider, used by passHostHeader
2015-11-23 08:38:35 +01:00
emile
6e62625ebf Add GetBool function in KV provider, used by passHostHeader 2015-11-22 23:39:43 +01:00
4 changed files with 88 additions and 8 deletions

View File

@@ -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]

View File

@@ -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

View File

@@ -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 .}}]

View File

@@ -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)
}