refactor: simplify template and use typed function.
This commit is contained in:
parent
750878d668
commit
b1ea36793b
4 changed files with 790 additions and 170 deletions
|
@ -893,45 +893,42 @@ var _templatesKvTmpl = []byte(`[backends]
|
||||||
{{range $backend := List .Prefix "/backends/" }}
|
{{range $backend := List .Prefix "/backends/" }}
|
||||||
{{ $backendName := Last $backend }}
|
{{ $backendName := Last $backend }}
|
||||||
|
|
||||||
{{$circuitBreaker := Get "" $backend "/circuitbreaker/expression"}}
|
{{ $circuitBreaker := getCircuitBreaker $backend }}
|
||||||
{{with $circuitBreaker}}
|
{{if $circuitBreaker }}
|
||||||
[backends."{{ $backendName }}".circuitBreaker]
|
[backends."{{ $backendName }}".circuitBreaker]
|
||||||
expression = "{{$circuitBreaker}}"
|
expression = "{{ $circuitBreaker.Expression }}"
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{$loadBalancer := Get "" $backend "/loadbalancer/method"}}
|
{{ $loadBalancer := getLoadBalancer $backend }}
|
||||||
{{with $loadBalancer}}
|
{{if $loadBalancer }}
|
||||||
[backends."{{ $backendName }}".loadBalancer]
|
[backends."{{ $backendName }}".loadBalancer]
|
||||||
method = "{{$loadBalancer}}"
|
method = "{{ $loadBalancer.Method }}"
|
||||||
sticky = {{ getSticky $backend }}
|
sticky = {{ $loadBalancer.Sticky }}
|
||||||
{{if hasStickinessLabel $backend}}
|
{{if $loadBalancer.Stickiness }}
|
||||||
[backends."{{ $backendName }}".loadBalancer.stickiness]
|
[backends."{{ $backendName }}".loadBalancer.stickiness]
|
||||||
cookieName = "{{getStickinessCookieName $backend}}"
|
cookieName = "{{ $loadBalancer.Stickiness.CookieName }}"
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{$maxConnAmt := Get "" $backend "/maxconn/amount"}}
|
{{ $maxConn := getMaxConn $backend }}
|
||||||
{{$maxConnExtractorFunc := Get "" $backend "/maxconn/extractorfunc"}}
|
{{if $maxConn }}
|
||||||
{{with $maxConnAmt}}
|
|
||||||
{{with $maxConnExtractorFunc}}
|
|
||||||
[backends."{{ $backendName }}".maxConn]
|
[backends."{{ $backendName }}".maxConn]
|
||||||
amount = {{$maxConnAmt}}
|
extractorFunc = "{{ $maxConn.ExtractorFunc }}"
|
||||||
extractorFunc = "{{$maxConnExtractorFunc}}"
|
amount = {{ $maxConn.Amount }}
|
||||||
{{end}}
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{$healthCheck := Get "" $backend "/healthcheck/path"}}
|
{{ $healthCheck := getHealthCheck $backend }}
|
||||||
{{with $healthCheck}}
|
{{if $healthCheck }}
|
||||||
[backends."{{$backendName}}".healthCheck]
|
[backends.{{ $backendName }}.healthCheck]
|
||||||
path = "{{$healthCheck}}"
|
path = "{{ $healthCheck.Path }}"
|
||||||
port = {{ Get "0" $backend "/healthcheck/port" }}
|
port = {{ $healthCheck.Port }}
|
||||||
interval = "{{ Get "30s" $backend "/healthcheck/interval" }}"
|
interval = "{{ $healthCheck.Interval }}"
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{range $server := ListServers $backend}}
|
{{range $serverName, $server := getServers $backend}}
|
||||||
[backends."{{$backendName}}".servers."{{Last $server}}"]
|
[backends."{{ $backendName }}".servers."{{ $serverName }}"]
|
||||||
url = "{{Get "" $server "/url"}}"
|
url = "{{ $server.URL }}"
|
||||||
weight = {{Get "0" $server "/weight"}}
|
weight = {{ $server.Weight }}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -941,23 +938,23 @@ var _templatesKvTmpl = []byte(`[backends]
|
||||||
{{ $frontendName := Last $frontend }}
|
{{ $frontendName := Last $frontend }}
|
||||||
|
|
||||||
[frontends."{{ $frontendName }}"]
|
[frontends."{{ $frontendName }}"]
|
||||||
backend = "{{Get "" $frontend "/backend"}}"
|
backend = "{{ getBackendName $frontend }}"
|
||||||
priority = {{Get "0" $frontend "/priority"}}
|
priority = {{ getPriority $frontend }}
|
||||||
passHostHeader = {{Get "true" $frontend "/passHostHeader"}}
|
passHostHeader = {{ getPassHostHeader $frontend }}
|
||||||
passTLSCert = {{Get "false" $frontend "/passtlscert"}}
|
passTLSCert = {{ getPassTLSCert $frontend }}
|
||||||
|
|
||||||
{{$entryPoints := SplitGet $frontend "/entrypoints"}}
|
entryPoints = [{{range getEntryPoints $frontend }}
|
||||||
entryPoints = [{{range $entryPoints}}
|
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{end}}]
|
||||||
|
|
||||||
{{$whitelistSourceRange := SplitGet $frontend "/whitelistsourcerange"}}
|
{{ $whitelistSourceRange := getWhitelistSourceRange $frontend }}
|
||||||
|
{{if $whitelistSourceRange }}
|
||||||
whitelistSourceRange = [{{range $whitelistSourceRange }}
|
whitelistSourceRange = [{{range $whitelistSourceRange }}
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{end}}]
|
||||||
|
{{end}}
|
||||||
|
|
||||||
{{$basicAuth := SplitGet $frontend "/basicauth"}}
|
basicAuth = [{{range getBasicAuth $frontend }}
|
||||||
basicAuth = [{{range $basicAuth}}
|
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{end}}]
|
||||||
|
|
||||||
|
@ -1048,25 +1045,23 @@ var _templatesKvTmpl = []byte(`[backends]
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{range $route := List $frontend "/routes/"}}
|
{{range $routeName, $route := getRoutes $frontend }}
|
||||||
[frontends."{{$frontendName}}".routes."{{Last $route}}"]
|
[frontends."{{ $frontendName }}".routes."{{ $routeName }}"]
|
||||||
rule = "{{Get "" $route "/rule"}}"
|
rule = "{{ $route.Rule }}"
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{range $tlsConfiguration := List .Prefix "/tlsconfiguration/"}}
|
{{range $tlsConfiguration := getTLSConfigurations .Prefix }}
|
||||||
|
|
||||||
[[tlsConfiguration]]
|
[[tlsConfiguration]]
|
||||||
|
|
||||||
{{$entryPoints := SplitGet $tlsConfiguration "/entrypoints"}}
|
entryPoints = [{{range $tlsConfiguration.EntryPoints }}
|
||||||
entryPoints = [{{range $entryPoints}}
|
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{end}}]
|
||||||
|
|
||||||
[tlsConfiguration.certificate]
|
[tlsConfiguration.certificate]
|
||||||
certFile = """{{Get "" $tlsConfiguration "/certificate/certfile"}}"""
|
certFile = """{{ $tlsConfiguration.Certificate.CertFile }}"""
|
||||||
keyFile = """{{Get "" $tlsConfiguration "/certificate/keyfile"}}"""
|
keyFile = """{{ $tlsConfiguration.Certificate.KeyFile }}"""
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
`)
|
`)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package kv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -12,6 +13,7 @@ import (
|
||||||
"github.com/containous/flaeg"
|
"github.com/containous/flaeg"
|
||||||
"github.com/containous/traefik/log"
|
"github.com/containous/traefik/log"
|
||||||
"github.com/containous/traefik/provider/label"
|
"github.com/containous/traefik/provider/label"
|
||||||
|
"github.com/containous/traefik/tls"
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
"github.com/docker/libkv/store"
|
"github.com/docker/libkv/store"
|
||||||
)
|
)
|
||||||
|
@ -35,16 +37,31 @@ func (p *Provider) buildConfiguration() *types.Configuration {
|
||||||
"Last": p.last,
|
"Last": p.last,
|
||||||
"Has": p.has,
|
"Has": p.has,
|
||||||
|
|
||||||
|
"getTLSConfigurations": p.getTLSConfigurations,
|
||||||
|
|
||||||
// Frontend functions
|
// Frontend functions
|
||||||
|
"getBackendName": p.getFuncString(pathFrontendBackend, ""),
|
||||||
|
"getPriority": p.getFuncInt(pathFrontendPriority, 0),
|
||||||
|
"getPassHostHeader": p.getFuncBool(pathFrontendPassHostHeader, true),
|
||||||
|
"getPassTLSCert": p.getFuncBool(pathFrontendPassTLSCert, label.DefaultPassTLSCert),
|
||||||
|
"getEntryPoints": p.getFuncSlice(pathFrontendEntryPoints),
|
||||||
|
"getWhitelistSourceRange": p.getFuncSlice(pathFrontendWhiteListSourceRange),
|
||||||
|
"getBasicAuth": p.getFuncSlice(pathFrontendBasicAuth),
|
||||||
|
"getRoutes": p.getRoutes,
|
||||||
"getRedirect": p.getRedirect,
|
"getRedirect": p.getRedirect,
|
||||||
"getErrorPages": p.getErrorPages,
|
"getErrorPages": p.getErrorPages,
|
||||||
"getRateLimit": p.getRateLimit,
|
"getRateLimit": p.getRateLimit,
|
||||||
"getHeaders": p.getHeaders,
|
"getHeaders": p.getHeaders,
|
||||||
|
|
||||||
// Backend functions
|
// Backend functions
|
||||||
"getSticky": p.getSticky,
|
"getServers": p.getServers,
|
||||||
"hasStickinessLabel": p.hasStickinessLabel,
|
"getCircuitBreaker": p.getCircuitBreaker,
|
||||||
"getStickinessCookieName": p.getStickinessCookieName,
|
"getLoadBalancer": p.getLoadBalancer,
|
||||||
|
"getMaxConn": p.getMaxConn,
|
||||||
|
"getHealthCheck": p.getHealthCheck,
|
||||||
|
"getSticky": p.getSticky, // Deprecated [breaking]
|
||||||
|
"hasStickinessLabel": p.hasStickinessLabel, // Deprecated [breaking]
|
||||||
|
"getStickinessCookieName": p.getStickinessCookieName, // Deprecated [breaking]
|
||||||
}
|
}
|
||||||
|
|
||||||
configuration, err := p.GetConfiguration("templates/kv.tmpl", KvFuncMap, templateObjects)
|
configuration, err := p.GetConfiguration("templates/kv.tmpl", KvFuncMap, templateObjects)
|
||||||
|
@ -61,6 +78,7 @@ func (p *Provider) buildConfiguration() *types.Configuration {
|
||||||
return configuration
|
return configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated
|
||||||
func (p *Provider) getSticky(rootPath string) bool {
|
func (p *Provider) getSticky(rootPath string) bool {
|
||||||
stickyValue := p.get("", rootPath, pathBackendLoadBalancerSticky)
|
stickyValue := p.get("", rootPath, pathBackendLoadBalancerSticky)
|
||||||
if len(stickyValue) > 0 {
|
if len(stickyValue) > 0 {
|
||||||
|
@ -77,10 +95,12 @@ func (p *Provider) getSticky(rootPath string) bool {
|
||||||
return sticky
|
return sticky
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated
|
||||||
func (p *Provider) hasStickinessLabel(rootPath string) bool {
|
func (p *Provider) hasStickinessLabel(rootPath string) bool {
|
||||||
return p.getBool(false, rootPath, pathBackendLoadBalancerStickiness)
|
return p.getBool(false, rootPath, pathBackendLoadBalancerStickiness)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated
|
||||||
func (p *Provider) getStickinessCookieName(rootPath string) string {
|
func (p *Provider) getStickinessCookieName(rootPath string) string {
|
||||||
return p.get("", rootPath, pathBackendLoadBalancerStickinessCookieName)
|
return p.get("", rootPath, pathBackendLoadBalancerStickinessCookieName)
|
||||||
}
|
}
|
||||||
|
@ -193,6 +213,145 @@ func (p *Provider) getHeaders(rootPath string) *types.Headers {
|
||||||
return headers
|
return headers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getLoadBalancer(rootPath string) *types.LoadBalancer {
|
||||||
|
lb := &types.LoadBalancer{
|
||||||
|
Method: p.get(label.DefaultBackendLoadBalancerMethod, rootPath, pathBackendLoadBalancerMethod),
|
||||||
|
Sticky: p.getSticky(rootPath),
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.getBool(false, rootPath, pathBackendLoadBalancerStickiness) {
|
||||||
|
lb.Stickiness = &types.Stickiness{
|
||||||
|
CookieName: p.get("", rootPath, pathBackendLoadBalancerStickinessCookieName),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getCircuitBreaker(rootPath string) *types.CircuitBreaker {
|
||||||
|
if !p.has(rootPath, pathBackendCircuitBreakerExpression) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
circuitBreaker := p.get(label.DefaultCircuitBreakerExpression, rootPath, pathBackendCircuitBreakerExpression)
|
||||||
|
if len(circuitBreaker) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.CircuitBreaker{Expression: circuitBreaker}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getMaxConn(rootPath string) *types.MaxConn {
|
||||||
|
amount := p.getInt64(math.MinInt64, rootPath, pathBackendMaxConnAmount)
|
||||||
|
extractorFunc := p.get(label.DefaultBackendMaxconnExtractorFunc, rootPath, pathBackendMaxConnExtractorFunc)
|
||||||
|
|
||||||
|
if amount == math.MinInt64 || len(extractorFunc) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.MaxConn{
|
||||||
|
Amount: amount,
|
||||||
|
ExtractorFunc: extractorFunc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getHealthCheck(rootPath string) *types.HealthCheck {
|
||||||
|
path := p.get("", rootPath, pathBackendHealthCheckPath)
|
||||||
|
|
||||||
|
if len(path) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
port := p.getInt(label.DefaultBackendHealthCheckPort, rootPath, pathBackendHealthCheckPort)
|
||||||
|
interval := p.get("30s", rootPath, pathBackendHealthCheckInterval)
|
||||||
|
|
||||||
|
return &types.HealthCheck{
|
||||||
|
Path: path,
|
||||||
|
Port: port,
|
||||||
|
Interval: interval,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getTLSConfigurations(prefix string) []*tls.Configuration {
|
||||||
|
var tlsConfiguration []*tls.Configuration
|
||||||
|
|
||||||
|
for _, tlsConfPath := range p.list(prefix, pathTLSConfiguration) {
|
||||||
|
certFile := p.get("", tlsConfPath, pathTLSConfigurationCertFile)
|
||||||
|
keyFile := p.get("", tlsConfPath, pathTLSConfigurationKeyFile)
|
||||||
|
|
||||||
|
if len(certFile) == 0 && len(keyFile) == 0 {
|
||||||
|
log.Warnf("Invalid TLS configuration (no cert and no key): %s", tlsConfPath)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
entryPoints := p.splitGet(tlsConfPath, pathTLSConfigurationEntryPoints)
|
||||||
|
if len(entryPoints) == 0 {
|
||||||
|
log.Warnf("Invalid TLS configuration (no entry points): %s", tlsConfPath)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConf := &tls.Configuration{
|
||||||
|
EntryPoints: entryPoints,
|
||||||
|
Certificate: &tls.Certificate{
|
||||||
|
CertFile: tls.FileOrContent(certFile),
|
||||||
|
KeyFile: tls.FileOrContent(keyFile),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfiguration = append(tlsConfiguration, tlsConf)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlsConfiguration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getRoutes(rootPath string) map[string]types.Route {
|
||||||
|
var routes map[string]types.Route
|
||||||
|
|
||||||
|
rts := p.list(rootPath, pathFrontendRoutes)
|
||||||
|
for _, rt := range rts {
|
||||||
|
|
||||||
|
rule := p.get("", rt, pathFrontendRule)
|
||||||
|
if len(rule) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if routes == nil {
|
||||||
|
routes = make(map[string]types.Route)
|
||||||
|
}
|
||||||
|
|
||||||
|
routeName := p.last(rt)
|
||||||
|
routes[routeName] = types.Route{
|
||||||
|
Rule: rule,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return routes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getServers(rootPath string) map[string]types.Server {
|
||||||
|
var servers map[string]types.Server
|
||||||
|
|
||||||
|
serverKeys := p.listServers(rootPath)
|
||||||
|
for _, serverKey := range serverKeys {
|
||||||
|
serverURL := p.get("", serverKey, pathBackendServerURL)
|
||||||
|
if len(serverURL) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if servers == nil {
|
||||||
|
servers = make(map[string]types.Server)
|
||||||
|
}
|
||||||
|
|
||||||
|
serverName := p.last(serverKey)
|
||||||
|
servers[serverName] = types.Server{
|
||||||
|
URL: serverURL,
|
||||||
|
Weight: p.getInt(0, serverKey, pathBackendServerWeight),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return servers
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) listServers(backend string) []string {
|
func (p *Provider) listServers(backend string) []string {
|
||||||
serverNames := p.list(backend, pathBackendServers)
|
serverNames := p.list(backend, pathBackendServers)
|
||||||
return fun.Filter(p.serverFilter, serverNames).([]string)
|
return fun.Filter(p.serverFilter, serverNames).([]string)
|
||||||
|
@ -229,6 +388,30 @@ func (p *Provider) checkConstraints(keys ...string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getFuncString(key string, defaultValue string) func(rootPath string) string {
|
||||||
|
return func(rootPath string) string {
|
||||||
|
return p.get(defaultValue, rootPath, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getFuncBool(key string, defaultValue bool) func(rootPath string) bool {
|
||||||
|
return func(rootPath string) bool {
|
||||||
|
return p.getBool(defaultValue, rootPath, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getFuncInt(key string, defaultValue int) func(rootPath string) int {
|
||||||
|
return func(rootPath string) int {
|
||||||
|
return p.getInt(defaultValue, rootPath, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getFuncSlice(key string) func(rootPath string) []string {
|
||||||
|
return func(rootPath string) []string {
|
||||||
|
return p.splitGet(rootPath, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) get(defaultValue string, keyParts ...string) string {
|
func (p *Provider) get(defaultValue string, keyParts ...string) string {
|
||||||
key := strings.Join(keyParts, "")
|
key := strings.Join(keyParts, "")
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ func TestProviderBuildConfiguration(t *testing.T) {
|
||||||
expected: &types.Configuration{
|
expected: &types.Configuration{
|
||||||
Backends: map[string]*types.Backend{
|
Backends: map[string]*types.Backend{
|
||||||
"backend.with.dot.too": {
|
"backend.with.dot.too": {
|
||||||
|
LoadBalancer: &types.LoadBalancer{Method: label.DefaultBackendLoadBalancerMethod},
|
||||||
Servers: map[string]types.Server{
|
Servers: map[string]types.Server{
|
||||||
"server.with.dot": {
|
"server.with.dot": {
|
||||||
URL: "http://172.17.0.2:80",
|
URL: "http://172.17.0.2:80",
|
||||||
|
@ -51,7 +52,6 @@ func TestProviderBuildConfiguration(t *testing.T) {
|
||||||
Backend: "backend.with.dot.too",
|
Backend: "backend.with.dot.too",
|
||||||
PassHostHeader: true,
|
PassHostHeader: true,
|
||||||
EntryPoints: []string{},
|
EntryPoints: []string{},
|
||||||
WhitelistSourceRange: []string{},
|
|
||||||
BasicAuth: []string{},
|
BasicAuth: []string{},
|
||||||
Routes: map[string]types.Route{
|
Routes: map[string]types.Route{
|
||||||
"route.with.dot": {
|
"route.with.dot": {
|
||||||
|
@ -1292,3 +1292,450 @@ func TestProviderGetHeaders(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProviderGetLoadBalancer(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
rootPath string
|
||||||
|
kvPairs []*store.KVPair
|
||||||
|
expected *types.LoadBalancer
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "when all keys",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendLoadBalancerMethod, "drr"),
|
||||||
|
withPair(pathBackendLoadBalancerSticky, "true"),
|
||||||
|
withPair(pathBackendLoadBalancerStickiness, "true"),
|
||||||
|
withPair(pathBackendLoadBalancerStickinessCookieName, "aubergine"))),
|
||||||
|
expected: &types.LoadBalancer{
|
||||||
|
Method: "drr",
|
||||||
|
Sticky: true,
|
||||||
|
Stickiness: &types.Stickiness{
|
||||||
|
CookieName: "aubergine",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when no specific configuration",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik", backend("foo")),
|
||||||
|
expected: &types.LoadBalancer{
|
||||||
|
Method: "wrr",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when method is set",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendLoadBalancerMethod, "drr"))),
|
||||||
|
expected: &types.LoadBalancer{
|
||||||
|
Method: "drr",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when sticky is set",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendLoadBalancerSticky, "true"))),
|
||||||
|
expected: &types.LoadBalancer{
|
||||||
|
Method: "wrr",
|
||||||
|
Sticky: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when stickiness is set",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendLoadBalancerStickiness, "true"))),
|
||||||
|
expected: &types.LoadBalancer{
|
||||||
|
Method: "wrr",
|
||||||
|
Stickiness: &types.Stickiness{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when stickiness cookie name is set",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendLoadBalancerStickiness, "true"),
|
||||||
|
withPair(pathBackendLoadBalancerStickinessCookieName, "aubergine"))),
|
||||||
|
expected: &types.LoadBalancer{
|
||||||
|
Method: "wrr",
|
||||||
|
Stickiness: &types.Stickiness{
|
||||||
|
CookieName: "aubergine",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when stickiness cookie name is set but not stickiness",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendLoadBalancerStickinessCookieName, "aubergine"))),
|
||||||
|
expected: &types.LoadBalancer{
|
||||||
|
Method: "wrr",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
p := newProviderMock(test.kvPairs)
|
||||||
|
|
||||||
|
result := p.getLoadBalancer(test.rootPath)
|
||||||
|
|
||||||
|
assert.Equal(t, test.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProviderGetCircuitBreaker(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
rootPath string
|
||||||
|
kvPairs []*store.KVPair
|
||||||
|
expected *types.CircuitBreaker
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "when cb expression defined",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendCircuitBreakerExpression, label.DefaultCircuitBreakerExpression))),
|
||||||
|
expected: &types.CircuitBreaker{
|
||||||
|
Expression: label.DefaultCircuitBreakerExpression,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when no cb expression",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik", backend("foo")),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
p := newProviderMock(test.kvPairs)
|
||||||
|
|
||||||
|
result := p.getCircuitBreaker(test.rootPath)
|
||||||
|
|
||||||
|
assert.Equal(t, test.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProviderGetMaxConn(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
rootPath string
|
||||||
|
kvPairs []*store.KVPair
|
||||||
|
expected *types.MaxConn
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "when max conn keys are defined",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendMaxConnAmount, "5"),
|
||||||
|
withPair(pathBackendMaxConnExtractorFunc, "client.ip"))),
|
||||||
|
expected: &types.MaxConn{
|
||||||
|
Amount: 5,
|
||||||
|
ExtractorFunc: "client.ip",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "should return nil when only extractor func is defined",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendMaxConnExtractorFunc, "client.ip"))),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when only amount is defined",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendMaxConnAmount, "5"))),
|
||||||
|
expected: &types.MaxConn{
|
||||||
|
Amount: 5,
|
||||||
|
ExtractorFunc: "request.host",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
p := newProviderMock(test.kvPairs)
|
||||||
|
|
||||||
|
result := p.getMaxConn(test.rootPath)
|
||||||
|
|
||||||
|
assert.Equal(t, test.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProviderGetHealthCheck(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
rootPath string
|
||||||
|
kvPairs []*store.KVPair
|
||||||
|
expected *types.HealthCheck
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "when all configuration keys defined",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendHealthCheckPath, "/health"),
|
||||||
|
withPair(pathBackendHealthCheckPort, "80"),
|
||||||
|
withPair(pathBackendHealthCheckInterval, "10s"))),
|
||||||
|
expected: &types.HealthCheck{
|
||||||
|
Interval: "10s",
|
||||||
|
Path: "/health",
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when only path defined",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendHealthCheckPath, "/health"))),
|
||||||
|
expected: &types.HealthCheck{
|
||||||
|
Interval: "30s",
|
||||||
|
Path: "/health",
|
||||||
|
Port: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "should return nil when no path",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendHealthCheckPort, "80"),
|
||||||
|
withPair(pathBackendHealthCheckInterval, "30s"))),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
p := newProviderMock(test.kvPairs)
|
||||||
|
|
||||||
|
result := p.getHealthCheck(test.rootPath)
|
||||||
|
|
||||||
|
assert.Equal(t, test.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProviderGetTLSConfigurations(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
kvPairs []*store.KVPair
|
||||||
|
expected []*tls.Configuration
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "when several TLS configuration defined",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
entry("tlsconfiguration/foo",
|
||||||
|
withPair("entrypoints", "http,https"),
|
||||||
|
withPair("certificate/certfile", "certfile1"),
|
||||||
|
withPair("certificate/keyfile", "keyfile1")),
|
||||||
|
entry("tlsconfiguration/bar",
|
||||||
|
withPair("entrypoints", "http,https"),
|
||||||
|
withPair("certificate/certfile", "certfile2"),
|
||||||
|
withPair("certificate/keyfile", "keyfile2"))),
|
||||||
|
expected: []*tls.Configuration{
|
||||||
|
{
|
||||||
|
EntryPoints: []string{"http", "https"},
|
||||||
|
Certificate: &tls.Certificate{
|
||||||
|
CertFile: "certfile2",
|
||||||
|
KeyFile: "keyfile2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
EntryPoints: []string{"http", "https"},
|
||||||
|
Certificate: &tls.Certificate{
|
||||||
|
CertFile: "certfile1",
|
||||||
|
KeyFile: "keyfile1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "should return nil when no TLS configuration",
|
||||||
|
kvPairs: filler("traefik", entry("tlsconfiguration/foo")),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "should return nil when no entry points",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
entry("tlsconfiguration/foo",
|
||||||
|
withPair("certificate/certfile", "certfile2"),
|
||||||
|
withPair("certificate/keyfile", "keyfile2"))),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "should return nil when no cert file and no key file",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
entry("tlsconfiguration/foo",
|
||||||
|
withPair("entrypoints", "http,https"))),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
prefix := "traefik"
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
p := newProviderMock(test.kvPairs)
|
||||||
|
|
||||||
|
result := p.getTLSConfigurations(prefix)
|
||||||
|
|
||||||
|
assert.Equal(t, test.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProviderGetRoutes(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
rootPath string
|
||||||
|
kvPairs []*store.KVPair
|
||||||
|
expected map[string]types.Route
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "should return nil when no data",
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "should return nil when route key exists but without rule key",
|
||||||
|
rootPath: "traefik/frontends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
frontend("foo",
|
||||||
|
withPair(pathFrontendRoutes+"bar", "test1"),
|
||||||
|
withPair(pathFrontendRoutes+"bir", "test2"))),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "should return a map when configuration keys are defined",
|
||||||
|
rootPath: "traefik/frontends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
frontend("foo",
|
||||||
|
withPair(pathFrontendRoutes+"bar"+pathFrontendRule, "test1"),
|
||||||
|
withPair(pathFrontendRoutes+"bir"+pathFrontendRule, "test2"))),
|
||||||
|
expected: map[string]types.Route{
|
||||||
|
"bar": {
|
||||||
|
Rule: "test1",
|
||||||
|
},
|
||||||
|
"bir": {
|
||||||
|
Rule: "test2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
p := newProviderMock(test.kvPairs)
|
||||||
|
|
||||||
|
result := p.getRoutes(test.rootPath)
|
||||||
|
|
||||||
|
assert.Equal(t, test.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProviderGetServers(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
rootPath string
|
||||||
|
kvPairs []*store.KVPair
|
||||||
|
expected map[string]types.Server
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "should return nil when no data",
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "should return nil when server has no URL",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendServers+"server1/weight", "7"),
|
||||||
|
withPair(pathBackendServers+"server2/weight", "6"))),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "should use default weight when invalid weight value",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendServers+"server1/url", "http://172.17.0.2:80"),
|
||||||
|
withPair(pathBackendServers+"server1/weight", "kls"))),
|
||||||
|
expected: map[string]types.Server{
|
||||||
|
"server1": {
|
||||||
|
URL: "http://172.17.0.2:80",
|
||||||
|
Weight: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "should return a map when configuration keys are defined",
|
||||||
|
rootPath: "traefik/backends/foo",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
backend("foo",
|
||||||
|
withPair(pathBackendServers+"server1/url", "http://172.17.0.2:80"),
|
||||||
|
withPair(pathBackendServers+"server2/url", "http://172.17.0.3:80"),
|
||||||
|
withPair(pathBackendServers+"server2/weight", "6"))),
|
||||||
|
expected: map[string]types.Server{
|
||||||
|
"server1": {
|
||||||
|
URL: "http://172.17.0.2:80",
|
||||||
|
Weight: 0,
|
||||||
|
},
|
||||||
|
"server2": {
|
||||||
|
URL: "http://172.17.0.3:80",
|
||||||
|
Weight: 6,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
p := newProviderMock(test.kvPairs)
|
||||||
|
|
||||||
|
result := p.getServers(test.rootPath)
|
||||||
|
|
||||||
|
assert.Equal(t, test.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,45 +2,42 @@
|
||||||
{{range $backend := List .Prefix "/backends/" }}
|
{{range $backend := List .Prefix "/backends/" }}
|
||||||
{{ $backendName := Last $backend }}
|
{{ $backendName := Last $backend }}
|
||||||
|
|
||||||
{{$circuitBreaker := Get "" $backend "/circuitbreaker/expression"}}
|
{{ $circuitBreaker := getCircuitBreaker $backend }}
|
||||||
{{with $circuitBreaker}}
|
{{if $circuitBreaker }}
|
||||||
[backends."{{ $backendName }}".circuitBreaker]
|
[backends."{{ $backendName }}".circuitBreaker]
|
||||||
expression = "{{$circuitBreaker}}"
|
expression = "{{ $circuitBreaker.Expression }}"
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{$loadBalancer := Get "" $backend "/loadbalancer/method"}}
|
{{ $loadBalancer := getLoadBalancer $backend }}
|
||||||
{{with $loadBalancer}}
|
{{if $loadBalancer }}
|
||||||
[backends."{{ $backendName }}".loadBalancer]
|
[backends."{{ $backendName }}".loadBalancer]
|
||||||
method = "{{$loadBalancer}}"
|
method = "{{ $loadBalancer.Method }}"
|
||||||
sticky = {{ getSticky $backend }}
|
sticky = {{ $loadBalancer.Sticky }}
|
||||||
{{if hasStickinessLabel $backend}}
|
{{if $loadBalancer.Stickiness }}
|
||||||
[backends."{{ $backendName }}".loadBalancer.stickiness]
|
[backends."{{ $backendName }}".loadBalancer.stickiness]
|
||||||
cookieName = "{{getStickinessCookieName $backend}}"
|
cookieName = "{{ $loadBalancer.Stickiness.CookieName }}"
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{$maxConnAmt := Get "" $backend "/maxconn/amount"}}
|
{{ $maxConn := getMaxConn $backend }}
|
||||||
{{$maxConnExtractorFunc := Get "" $backend "/maxconn/extractorfunc"}}
|
{{if $maxConn }}
|
||||||
{{with $maxConnAmt}}
|
|
||||||
{{with $maxConnExtractorFunc}}
|
|
||||||
[backends."{{ $backendName }}".maxConn]
|
[backends."{{ $backendName }}".maxConn]
|
||||||
amount = {{$maxConnAmt}}
|
extractorFunc = "{{ $maxConn.ExtractorFunc }}"
|
||||||
extractorFunc = "{{$maxConnExtractorFunc}}"
|
amount = {{ $maxConn.Amount }}
|
||||||
{{end}}
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{$healthCheck := Get "" $backend "/healthcheck/path"}}
|
{{ $healthCheck := getHealthCheck $backend }}
|
||||||
{{with $healthCheck}}
|
{{if $healthCheck }}
|
||||||
[backends."{{$backendName}}".healthCheck]
|
[backends.{{ $backendName }}.healthCheck]
|
||||||
path = "{{$healthCheck}}"
|
path = "{{ $healthCheck.Path }}"
|
||||||
port = {{ Get "0" $backend "/healthcheck/port" }}
|
port = {{ $healthCheck.Port }}
|
||||||
interval = "{{ Get "30s" $backend "/healthcheck/interval" }}"
|
interval = "{{ $healthCheck.Interval }}"
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{range $server := ListServers $backend}}
|
{{range $serverName, $server := getServers $backend}}
|
||||||
[backends."{{$backendName}}".servers."{{Last $server}}"]
|
[backends."{{ $backendName }}".servers."{{ $serverName }}"]
|
||||||
url = "{{Get "" $server "/url"}}"
|
url = "{{ $server.URL }}"
|
||||||
weight = {{Get "0" $server "/weight"}}
|
weight = {{ $server.Weight }}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -50,23 +47,23 @@
|
||||||
{{ $frontendName := Last $frontend }}
|
{{ $frontendName := Last $frontend }}
|
||||||
|
|
||||||
[frontends."{{ $frontendName }}"]
|
[frontends."{{ $frontendName }}"]
|
||||||
backend = "{{Get "" $frontend "/backend"}}"
|
backend = "{{ getBackendName $frontend }}"
|
||||||
priority = {{Get "0" $frontend "/priority"}}
|
priority = {{ getPriority $frontend }}
|
||||||
passHostHeader = {{Get "true" $frontend "/passHostHeader"}}
|
passHostHeader = {{ getPassHostHeader $frontend }}
|
||||||
passTLSCert = {{Get "false" $frontend "/passtlscert"}}
|
passTLSCert = {{ getPassTLSCert $frontend }}
|
||||||
|
|
||||||
{{$entryPoints := SplitGet $frontend "/entrypoints"}}
|
entryPoints = [{{range getEntryPoints $frontend }}
|
||||||
entryPoints = [{{range $entryPoints}}
|
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{end}}]
|
||||||
|
|
||||||
{{$whitelistSourceRange := SplitGet $frontend "/whitelistsourcerange"}}
|
{{ $whitelistSourceRange := getWhitelistSourceRange $frontend }}
|
||||||
|
{{if $whitelistSourceRange }}
|
||||||
whitelistSourceRange = [{{range $whitelistSourceRange }}
|
whitelistSourceRange = [{{range $whitelistSourceRange }}
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{end}}]
|
||||||
|
{{end}}
|
||||||
|
|
||||||
{{$basicAuth := SplitGet $frontend "/basicauth"}}
|
basicAuth = [{{range getBasicAuth $frontend }}
|
||||||
basicAuth = [{{range $basicAuth}}
|
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{end}}]
|
||||||
|
|
||||||
|
@ -157,24 +154,22 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{range $route := List $frontend "/routes/"}}
|
{{range $routeName, $route := getRoutes $frontend }}
|
||||||
[frontends."{{$frontendName}}".routes."{{Last $route}}"]
|
[frontends."{{ $frontendName }}".routes."{{ $routeName }}"]
|
||||||
rule = "{{Get "" $route "/rule"}}"
|
rule = "{{ $route.Rule }}"
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{range $tlsConfiguration := List .Prefix "/tlsconfiguration/"}}
|
{{range $tlsConfiguration := getTLSConfigurations .Prefix }}
|
||||||
|
|
||||||
[[tlsConfiguration]]
|
[[tlsConfiguration]]
|
||||||
|
|
||||||
{{$entryPoints := SplitGet $tlsConfiguration "/entrypoints"}}
|
entryPoints = [{{range $tlsConfiguration.EntryPoints }}
|
||||||
entryPoints = [{{range $entryPoints}}
|
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{end}}]
|
||||||
|
|
||||||
[tlsConfiguration.certificate]
|
[tlsConfiguration.certificate]
|
||||||
certFile = """{{Get "" $tlsConfiguration "/certificate/certfile"}}"""
|
certFile = """{{ $tlsConfiguration.Certificate.CertFile }}"""
|
||||||
keyFile = """{{Get "" $tlsConfiguration "/certificate/keyfile"}}"""
|
keyFile = """{{ $tlsConfiguration.Certificate.KeyFile }}"""
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
Loading…
Reference in a new issue