2018-11-14 09:18:03 +00:00
|
|
|
package provider
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"strings"
|
|
|
|
"text/template"
|
|
|
|
|
|
|
|
"github.com/BurntSushi/toml"
|
|
|
|
"github.com/Masterminds/sprig"
|
|
|
|
"github.com/containous/traefik/config"
|
|
|
|
"github.com/containous/traefik/log"
|
2019-03-14 08:30:04 +00:00
|
|
|
"github.com/containous/traefik/tls"
|
2018-11-14 09:18:03 +00:00
|
|
|
"github.com/containous/traefik/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
// BaseProvider should be inherited by providers.
|
|
|
|
type BaseProvider struct {
|
|
|
|
Watch bool `description:"Watch provider" export:"true"`
|
|
|
|
Filename string `description:"Override default configuration template. For advanced users :)" export:"true"`
|
|
|
|
Constraints types.Constraints `description:"Filter services by constraint, matching with Traefik tags." export:"true"`
|
|
|
|
Trace bool `description:"Display additional provider logs (if available)." export:"true"`
|
|
|
|
DebugLogGeneratedTemplate bool `description:"Enable debug logging of generated configuration template." export:"true"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// Init for compatibility reason the BaseProvider implements an empty Init.
|
2018-11-27 16:42:04 +00:00
|
|
|
func (p *BaseProvider) Init() error {
|
2018-11-14 09:18:03 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MatchConstraints must match with EVERY single constraint
|
|
|
|
// returns first constraint that do not match or nil.
|
|
|
|
func (p *BaseProvider) MatchConstraints(tags []string) (bool, *types.Constraint) {
|
|
|
|
// if there is no tags and no constraints, filtering is disabled
|
|
|
|
if len(tags) == 0 && len(p.Constraints) == 0 {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, constraint := range p.Constraints {
|
|
|
|
// xor: if ok and constraint.MustMatch are equal, then no tag is currently matching with the constraint
|
|
|
|
if ok := constraint.MatchConstraintWithAtLeastOneTag(tags); ok != constraint.MustMatch {
|
|
|
|
return false, constraint
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If no constraint or every constraints matching
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateConfiguration creates a provider configuration from content using templating.
|
|
|
|
func (p *BaseProvider) CreateConfiguration(tmplContent string, funcMap template.FuncMap, templateObjects interface{}) (*config.Configuration, error) {
|
|
|
|
var defaultFuncMap = sprig.TxtFuncMap()
|
|
|
|
// tolower is deprecated in favor of sprig's lower function
|
|
|
|
defaultFuncMap["tolower"] = strings.ToLower
|
|
|
|
defaultFuncMap["normalize"] = Normalize
|
|
|
|
defaultFuncMap["split"] = split
|
|
|
|
for funcID, funcElement := range funcMap {
|
|
|
|
defaultFuncMap[funcID] = funcElement
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpl := template.New(p.Filename).Funcs(defaultFuncMap)
|
|
|
|
|
|
|
|
_, err := tmpl.Parse(tmplContent)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var buffer bytes.Buffer
|
|
|
|
err = tmpl.Execute(&buffer, templateObjects)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var renderedTemplate = buffer.String()
|
|
|
|
if p.DebugLogGeneratedTemplate {
|
|
|
|
log.Debugf("Template content: %s", tmplContent)
|
|
|
|
log.Debugf("Rendering results: %s", renderedTemplate)
|
|
|
|
}
|
|
|
|
return p.DecodeConfiguration(renderedTemplate)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DecodeConfiguration Decodes a *types.Configuration from a content.
|
|
|
|
func (p *BaseProvider) DecodeConfiguration(content string) (*config.Configuration, error) {
|
2019-03-14 08:30:04 +00:00
|
|
|
configuration := &config.Configuration{
|
|
|
|
HTTP: &config.HTTPConfiguration{
|
|
|
|
Routers: make(map[string]*config.Router),
|
|
|
|
Middlewares: make(map[string]*config.Middleware),
|
|
|
|
Services: make(map[string]*config.Service),
|
|
|
|
},
|
|
|
|
TCP: &config.TCPConfiguration{
|
|
|
|
Routers: make(map[string]*config.TCPRouter),
|
|
|
|
Services: make(map[string]*config.TCPService),
|
|
|
|
},
|
|
|
|
TLS: make([]*tls.Configuration, 0),
|
|
|
|
TLSStores: make(map[string]tls.Store),
|
|
|
|
TLSOptions: make(map[string]tls.TLS),
|
|
|
|
}
|
2018-11-14 09:18:03 +00:00
|
|
|
if _, err := toml.Decode(content, configuration); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return configuration, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func split(sep, s string) []string {
|
|
|
|
return strings.Split(s, sep)
|
|
|
|
}
|