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"
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 18:35:01 +03:00
"github.com/emilevauge/traefik/types"
2015-10-01 13:04:25 +03:00
)
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
} {
provider . Prefix ,
}
var KvFuncMap = template . FuncMap {
2015-12-02 10:56:12 +03:00
"List" : provider . list ,
"Get" : provider . get ,
"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 {
2015-11-13 13:50:32 +03:00
log . Error ( "Error getting keys: " , 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
2015-11-13 13:50:32 +03:00
func ( provider * Kv ) get ( keys ... string ) string {
joinedKeys := strings . Join ( keys , "" )
keyPair , err := provider . kvclient . Get ( joinedKeys )
if err != nil {
2015-11-22 23:24:43 +03:00
log . Error ( "Error getting key: " , joinedKeys , err )
2015-11-13 13:50:32 +03:00
return ""
} else if keyPair == nil {
return ""
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
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
}