Added support for templates to file provider
This commit is contained in:
parent
d2e84a700f
commit
1a411b658b
5 changed files with 59 additions and 28 deletions
|
@ -239,8 +239,8 @@ func (gc *GlobalConfiguration) SetEffectiveConfiguration(configFile string) {
|
|||
}
|
||||
|
||||
// Try to fallback to traefik config file in case the file provider is enabled
|
||||
// but has no file name configured.
|
||||
if gc.File != nil && len(gc.File.Filename) == 0 {
|
||||
// but has no file name configured and is not in a directory mode.
|
||||
if gc.File != nil && len(gc.File.Filename) == 0 && len(gc.File.Directory) == 0 {
|
||||
if len(configFile) > 0 {
|
||||
gc.File.Filename = configFile
|
||||
} else {
|
||||
|
|
|
@ -77,6 +77,11 @@ func TestSetEffectiveConfigurationFileProviderFilename(t *testing.T) {
|
|||
fileProvider: &file.Provider{BaseProvider: provider.BaseProvider{Filename: "other.toml"}},
|
||||
wantFileProviderFilename: "other.toml",
|
||||
},
|
||||
{
|
||||
desc: "directory for file provider given",
|
||||
fileProvider: &file.Provider{Directory: "/"},
|
||||
wantFileProviderFilename: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
|
@ -7,8 +7,8 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/containous/traefik/log"
|
||||
"github.com/containous/traefik/provider"
|
||||
"github.com/containous/traefik/safe"
|
||||
|
@ -56,9 +56,9 @@ func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *s
|
|||
// and returns a 'Configuration' object
|
||||
func (p *Provider) BuildConfiguration() (*types.Configuration, error) {
|
||||
if p.Directory != "" {
|
||||
return loadFileConfigFromDirectory(p.Directory, nil)
|
||||
return p.loadFileConfigFromDirectory(p.Directory, nil)
|
||||
}
|
||||
return loadFileConfig(p.Filename)
|
||||
return p.loadFileConfig(p.Filename)
|
||||
}
|
||||
|
||||
func (p *Provider) addWatcher(pool *safe.Pool, directory string, configurationChan chan<- types.ConfigMessage, callback func(chan<- types.ConfigMessage, fsnotify.Event)) error {
|
||||
|
@ -125,18 +125,36 @@ func sendConfigToChannel(configurationChan chan<- types.ConfigMessage, configura
|
|||
}
|
||||
}
|
||||
|
||||
func loadFileConfig(filename string) (*types.Configuration, error) {
|
||||
configuration := &types.Configuration{
|
||||
Frontends: make(map[string]*types.Frontend),
|
||||
Backends: make(map[string]*types.Backend),
|
||||
func readFile(filename string) (string, error) {
|
||||
if len(filename) > 0 {
|
||||
buf, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
if _, err := toml.DecodeFile(filename, configuration); err != nil {
|
||||
return nil, fmt.Errorf("error reading configuration file: %s", err)
|
||||
}
|
||||
return configuration, nil
|
||||
return "", fmt.Errorf("invalid filename: %s", filename)
|
||||
}
|
||||
|
||||
func loadFileConfigFromDirectory(directory string, configuration *types.Configuration) (*types.Configuration, error) {
|
||||
func (p *Provider) loadFileConfig(filename string) (*types.Configuration, error) {
|
||||
fileContent, err := readFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading configuration file: %s - %s", filename, err)
|
||||
}
|
||||
configuration, err := p.CreateConfiguration(fileContent, template.FuncMap{}, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if configuration == nil || configuration.Backends == nil && configuration.Frontends == nil && configuration.TLS == nil {
|
||||
configuration = &types.Configuration{
|
||||
Frontends: make(map[string]*types.Frontend),
|
||||
Backends: make(map[string]*types.Backend),
|
||||
}
|
||||
}
|
||||
return configuration, err
|
||||
}
|
||||
|
||||
func (p *Provider) loadFileConfigFromDirectory(directory string, configuration *types.Configuration) (*types.Configuration, error) {
|
||||
fileList, err := ioutil.ReadDir(directory)
|
||||
|
||||
if err != nil {
|
||||
|
@ -154,17 +172,17 @@ func loadFileConfigFromDirectory(directory string, configuration *types.Configur
|
|||
for _, item := range fileList {
|
||||
|
||||
if item.IsDir() {
|
||||
configuration, err = loadFileConfigFromDirectory(filepath.Join(directory, item.Name()), configuration)
|
||||
configuration, err = p.loadFileConfigFromDirectory(filepath.Join(directory, item.Name()), configuration)
|
||||
if err != nil {
|
||||
return configuration, fmt.Errorf("unable to load content configuration from subdirectory %s: %v", item, err)
|
||||
}
|
||||
continue
|
||||
} else if !strings.HasSuffix(item.Name(), ".toml") {
|
||||
} else if !strings.HasSuffix(item.Name(), ".toml") && !strings.HasSuffix(item.Name(), ".tmpl") {
|
||||
continue
|
||||
}
|
||||
|
||||
var c *types.Configuration
|
||||
c, err = loadFileConfig(path.Join(directory, item.Name()))
|
||||
c, err = p.loadFileConfig(path.Join(directory, item.Name()))
|
||||
|
||||
if err != nil {
|
||||
return configuration, err
|
||||
|
|
|
@ -276,10 +276,13 @@ func createSubDir(t *testing.T, rootDir, dir string) string {
|
|||
|
||||
// createFrontendConfiguration Helper
|
||||
func createFrontendConfiguration(n int) string {
|
||||
conf := "[frontends]\n"
|
||||
conf := "{{$home := env \"HOME\"}}\n[frontends]\n"
|
||||
for i := 1; i <= n; i++ {
|
||||
conf += fmt.Sprintf(` [frontends.frontend%[1]d]
|
||||
conf += fmt.Sprintf(` [frontends."frontend%[1]d"]
|
||||
backend = "backend%[1]d"
|
||||
`, i)
|
||||
conf += fmt.Sprintf(` [frontends."frontend%[1]d".headers]
|
||||
"PublicKey" = "{{$home}}/pub.key"
|
||||
`, i)
|
||||
}
|
||||
return conf
|
||||
|
|
|
@ -50,8 +50,17 @@ func (p *BaseProvider) MatchConstraints(tags []string) (bool, *types.Constraint)
|
|||
return true, nil
|
||||
}
|
||||
|
||||
// GetConfiguration return the provider configuration using templating
|
||||
func (p *BaseProvider) GetConfiguration(defaultTemplateFile string, funcMap template.FuncMap, templateObjects interface{}) (*types.Configuration, error) {
|
||||
// GetConfiguration return the provider configuration from default template (file or content) or overrode template file
|
||||
func (p *BaseProvider) GetConfiguration(defaultTemplate string, funcMap template.FuncMap, templateObjects interface{}) (*types.Configuration, error) {
|
||||
tmplContent, err := p.getTemplateContent(defaultTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.CreateConfiguration(tmplContent, funcMap, templateObjects)
|
||||
}
|
||||
|
||||
// CreateConfiguration create a provider configuration from content using templating
|
||||
func (p *BaseProvider) CreateConfiguration(tmplContent string, funcMap template.FuncMap, templateObjects interface{}) (*types.Configuration, error) {
|
||||
configuration := new(types.Configuration)
|
||||
|
||||
var defaultFuncMap = sprig.TxtFuncMap()
|
||||
|
@ -65,12 +74,7 @@ func (p *BaseProvider) GetConfiguration(defaultTemplateFile string, funcMap temp
|
|||
|
||||
tmpl := template.New(p.Filename).Funcs(defaultFuncMap)
|
||||
|
||||
tmplContent, err := p.getTemplateContent(defaultTemplateFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = tmpl.Parse(tmplContent)
|
||||
_, err := tmpl.Parse(tmplContent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -83,7 +87,8 @@ func (p *BaseProvider) GetConfiguration(defaultTemplateFile string, funcMap temp
|
|||
|
||||
var renderedTemplate = buffer.String()
|
||||
if p.DebugLogGeneratedTemplate {
|
||||
log.Debugf("Rendering results of %s:\n%s", defaultTemplateFile, renderedTemplate)
|
||||
log.Debugf("Template content: %s", tmplContent)
|
||||
log.Debugf("Rendering results: %s", renderedTemplate)
|
||||
}
|
||||
if _, err := toml.Decode(renderedTemplate, configuration); err != nil {
|
||||
return nil, err
|
||||
|
|
Loading…
Reference in a new issue