2017-04-17 12:50:02 +02:00
package file
2015-09-07 15:25:13 +02:00
import (
2015-09-07 17:39:22 +02:00
"os"
"path/filepath"
"strings"
2015-09-24 17:16:13 +02:00
"github.com/BurntSushi/toml"
2016-08-18 14:20:11 +02:00
"github.com/containous/traefik/log"
2017-04-17 12:50:02 +02:00
"github.com/containous/traefik/provider"
2016-03-31 18:57:08 +02:00
"github.com/containous/traefik/safe"
2016-02-24 16:43:39 +01:00
"github.com/containous/traefik/types"
2015-09-24 17:16:13 +02:00
"gopkg.in/fsnotify.v1"
2015-09-07 15:25:13 +02:00
)
2017-04-17 12:50:02 +02:00
var _ provider . Provider = ( * Provider ) ( nil )
2016-08-16 19:13:18 +02:00
2017-04-17 12:50:02 +02:00
// Provider holds configurations of the provider.
type Provider struct {
provider . BaseProvider ` mapstructure:",squash" `
2015-09-07 15:25:13 +02:00
}
2017-04-17 12:50:02 +02:00
// Provide allows the file provider to provide configurations to traefik
2015-11-01 19:29:47 +01:00
// using the given configuration channel.
2017-04-17 12:50:02 +02:00
func ( p * Provider ) Provide ( configurationChan chan <- types . ConfigMessage , pool * safe . Pool , constraints types . Constraints ) error {
2015-09-07 15:25:13 +02:00
watcher , err := fsnotify . NewWatcher ( )
if err != nil {
2015-09-11 16:37:13 +02:00
log . Error ( "Error creating file watcher" , err )
2015-10-01 12:04:25 +02:00
return err
2015-09-07 15:25:13 +02:00
}
2017-04-17 12:50:02 +02:00
file , err := os . Open ( p . Filename )
2015-09-07 15:25:13 +02:00
if err != nil {
2015-09-11 16:37:13 +02:00
log . Error ( "Error opening file" , err )
2015-10-01 12:04:25 +02:00
return err
2015-09-07 15:25:13 +02:00
}
2015-09-07 17:39:22 +02:00
defer file . Close ( )
2015-09-07 15:25:13 +02:00
2017-04-17 12:50:02 +02:00
if p . Watch {
2015-10-03 16:50:53 +02:00
// Process events
2016-04-13 20:36:23 +02:00
pool . Go ( func ( stop chan bool ) {
2015-10-03 16:50:53 +02:00
defer watcher . Close ( )
for {
select {
2016-04-13 20:36:23 +02:00
case <- stop :
return
2015-10-03 16:50:53 +02:00
case event := <- watcher . Events :
if strings . Contains ( event . Name , file . Name ( ) ) {
2017-04-17 12:50:02 +02:00
log . Debug ( "Provider event:" , event )
configuration := p . loadFileConfig ( file . Name ( ) )
2015-10-03 16:50:53 +02:00
if configuration != nil {
2015-11-13 11:50:32 +01:00
configurationChan <- types . ConfigMessage {
ProviderName : "file" ,
Configuration : configuration ,
}
2015-10-03 16:50:53 +02:00
}
2015-09-07 23:25:07 +02:00
}
2015-10-03 16:50:53 +02:00
case error := <- watcher . Errors :
log . Error ( "Watcher event error" , error )
2015-09-07 17:39:22 +02:00
}
2015-09-07 15:25:13 +02:00
}
2016-03-31 18:57:08 +02:00
} )
2015-09-07 18:10:33 +02:00
err = watcher . Add ( filepath . Dir ( file . Name ( ) ) )
2015-10-03 16:50:53 +02:00
if err != nil {
log . Error ( "Error adding file watcher" , err )
return err
}
2015-09-07 17:39:22 +02:00
}
2015-09-07 15:25:13 +02:00
2017-04-17 12:50:02 +02:00
configuration := p . loadFileConfig ( file . Name ( ) )
2015-11-13 11:50:32 +01:00
configurationChan <- types . ConfigMessage {
ProviderName : "file" ,
Configuration : configuration ,
}
2015-10-01 12:04:25 +02:00
return nil
2015-09-07 15:25:13 +02:00
}
2017-04-17 12:50:02 +02:00
func ( p * Provider ) loadFileConfig ( filename string ) * types . Configuration {
2015-11-01 16:35:01 +01:00
configuration := new ( types . Configuration )
2015-09-08 00:15:14 +02:00
if _ , err := toml . DecodeFile ( filename , configuration ) ; err != nil {
2015-09-11 16:37:13 +02:00
log . Error ( "Error reading file:" , err )
2015-09-07 15:25:13 +02:00
return nil
}
2015-09-08 00:15:14 +02:00
return configuration
2015-09-12 15:10:03 +02:00
}