forked from traefik/traefik
-
Notifications
You must be signed in to change notification settings - Fork 0
/
provider.go
121 lines (106 loc) · 3.8 KB
/
provider.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package provider
import (
"bytes"
"io/ioutil"
"strings"
"text/template"
"unicode"
"github.com/BurntSushi/toml"
"github.com/Masterminds/sprig"
"github.com/containous/traefik/autogen"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types"
)
// Provider defines methods of a provider.
type Provider interface {
// Provide allows the provider to provide configurations to traefik
// using the given configuration channel.
Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error
}
// 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"`
}
// MatchConstraints must match with EVERY single contraint
// 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
}
// GetConfiguration return the provider configuration using templating
func (p *BaseProvider) GetConfiguration(defaultTemplateFile string, funcMap template.FuncMap, templateObjects interface{}) (*types.Configuration, error) {
var (
buf []byte
err error
)
configuration := new(types.Configuration)
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)
if len(p.Filename) > 0 {
buf, err = ioutil.ReadFile(p.Filename)
if err != nil {
return nil, err
}
} else {
buf, err = autogen.Asset(defaultTemplateFile)
if err != nil {
return nil, err
}
}
_, err = tmpl.Parse(string(buf))
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("Rendering results of %s:\n%s", defaultTemplateFile, renderedTemplate)
}
if _, err := toml.Decode(renderedTemplate, configuration); err != nil {
return nil, err
}
return configuration, nil
}
func split(sep, s string) []string {
return strings.Split(s, sep)
}
// Normalize transform a string that work with the rest of traefik
func Normalize(name string) string {
fargs := func(c rune) bool {
return !unicode.IsLetter(c) && !unicode.IsNumber(c)
}
// get function
return strings.Join(strings.FieldsFunc(name, fargs), "-")
}
// ReverseStringSlice invert the order of the given slice of string
func ReverseStringSlice(slice *[]string) {
for i, j := 0, len(*slice)-1; i < j; i, j = i+1, j-1 {
(*slice)[i], (*slice)[j] = (*slice)[j], (*slice)[i]
}
}