2015-11-01 21:29:47 +03:00
// Package provider holds the different provider implementation.
2015-11-01 18:35:01 +03:00
package provider
2015-10-01 13:04:25 +03:00
import (
"strings"
"text/template"
2015-11-01 18:35:01 +03:00
"time"
2015-10-01 13:04:25 +03:00
"github.com/BurntSushi/ty/fun"
log "github.com/Sirupsen/logrus"
2016-02-24 18:43:39 +03:00
"github.com/containous/traefik/types"
2015-11-01 18:35:01 +03:00
"github.com/docker/libkv"
2015-10-01 13:04:25 +03:00
"github.com/docker/libkv/store"
)
2015-11-01 21:29:47 +03:00
// Kv holds common configurations of key-value providers.
2015-11-02 21:48:34 +03:00
type Kv struct {
2016-01-14 00:46:44 +03:00
BaseProvider ` mapstructure:",squash" `
Endpoint string
Prefix string
storeType store . Backend
kvclient store . Store
2015-10-01 13:04:25 +03:00
}
2015-11-02 21:48:34 +03:00
func ( provider * Kv ) provide ( configurationChan chan <- types . ConfigMessage ) error {
2015-10-01 13:04:25 +03:00
kv , err := libkv . NewStore (
2016-01-14 00:46:44 +03:00
provider . storeType ,
2015-10-01 13:04:25 +03:00
[ ] string { provider . Endpoint } ,
& store . Config {
ConnectionTimeout : 30 * time . Second ,
2015-10-23 19:59:08 +03:00
Bucket : "traefik" ,
2015-10-01 13:04:25 +03:00
} ,
)
if err != nil {
return err
}
if _ , err := kv . List ( "" ) ; err != nil {
return err
}
provider . kvclient = kv
if provider . Watch {
stopCh := make ( chan struct { } )
chanKeys , err := kv . WatchTree ( provider . Prefix , stopCh )
if err != nil {
return err
}
go func ( ) {
for {
<- chanKeys
configuration := provider . loadConfig ( )
if configuration != nil {
2015-11-13 13:50:32 +03:00
configurationChan <- types . ConfigMessage {
2016-01-14 00:46:44 +03:00
ProviderName : string ( provider . storeType ) ,
2015-11-13 13:50:32 +03:00
Configuration : configuration ,
}
2015-10-01 13:04:25 +03:00
}
defer close ( stopCh )
}
} ( )
}
configuration := provider . loadConfig ( )
2015-11-13 13:50:32 +03:00
configurationChan <- types . ConfigMessage {
2016-01-14 00:46:44 +03:00
ProviderName : string ( provider . storeType ) ,
2015-11-13 13:50:32 +03:00
Configuration : configuration ,
}
2015-10-01 13:04:25 +03:00
return nil
}
2015-11-02 21:48:34 +03:00
func ( provider * Kv ) loadConfig ( ) * types . Configuration {
2015-10-01 13:04:25 +03:00
templateObjects := struct {
Prefix string
} {
2016-02-16 02:14:21 +03:00
// Allow `/traefik/alias` to superesede `provider.Prefix`
strings . TrimSuffix ( provider . get ( provider . Prefix , provider . Prefix + "/alias" ) , "/" ) ,
2015-10-01 13:04:25 +03:00
}
var KvFuncMap = template . FuncMap {
2016-02-01 18:08:58 +03:00
"List" : provider . list ,
"Get" : provider . get ,
"SplitGet" : provider . splitGet ,
"Last" : provider . last ,
2015-10-01 13:04:25 +03:00
}
2015-11-13 13:50:32 +03:00
configuration , err := provider . getConfiguration ( "templates/kv.tmpl" , KvFuncMap , templateObjects )
if err != nil {
log . Error ( err )
2015-10-01 13:04:25 +03:00
}
2015-11-13 13:50:32 +03:00
return configuration
}
2015-10-01 13:04:25 +03:00
2015-11-13 13:50:32 +03:00
func ( provider * Kv ) list ( keys ... string ) [ ] string {
joinedKeys := strings . Join ( keys , "" )
keysPairs , err := provider . kvclient . List ( joinedKeys )
2015-10-01 13:04:25 +03:00
if err != nil {
2016-02-01 18:08:58 +03:00
log . Errorf ( "Error getting keys %s %s " , joinedKeys , err )
2015-10-01 13:04:25 +03:00
return nil
}
2015-11-13 13:50:32 +03:00
directoryKeys := make ( map [ string ] string )
for _ , key := range keysPairs {
directory := strings . Split ( strings . TrimPrefix ( key . Key , strings . TrimPrefix ( joinedKeys , "/" ) ) , "/" ) [ 0 ]
directoryKeys [ directory ] = joinedKeys + directory
}
return fun . Values ( directoryKeys ) . ( [ ] string )
}
2015-10-01 13:04:25 +03:00
2016-02-01 18:08:58 +03:00
func ( provider * Kv ) get ( defaultValue string , keys ... string ) string {
2015-11-13 13:50:32 +03:00
joinedKeys := strings . Join ( keys , "" )
keyPair , err := provider . kvclient . Get ( joinedKeys )
if err != nil {
2016-02-01 18:08:58 +03:00
log . Warnf ( "Error getting key %s %s, setting default %s" , joinedKeys , err , defaultValue )
return defaultValue
2015-11-13 13:50:32 +03:00
} else if keyPair == nil {
2016-02-01 18:08:58 +03:00
log . Warnf ( "Error getting key %s, setting default %s" , joinedKeys , defaultValue )
return defaultValue
2015-10-01 13:04:25 +03:00
}
2015-11-13 13:50:32 +03:00
return string ( keyPair . Value )
}
2015-10-01 13:04:25 +03:00
2016-02-01 18:08:58 +03:00
func ( provider * Kv ) splitGet ( keys ... string ) [ ] string {
joinedKeys := strings . Join ( keys , "" )
keyPair , err := provider . kvclient . Get ( joinedKeys )
if err != nil {
log . Warnf ( "Error getting key %s %s, setting default empty" , joinedKeys , err )
return [ ] string { }
} else if keyPair == nil {
log . Warnf ( "Error getting key %s, setting default %empty" , joinedKeys )
return [ ] string { }
}
return strings . Split ( string ( keyPair . Value ) , "," )
}
2015-11-13 13:50:32 +03:00
func ( provider * Kv ) last ( key string ) string {
splittedKey := strings . Split ( key , "/" )
return splittedKey [ len ( splittedKey ) - 1 ]
2015-10-01 13:04:25 +03:00
}