feat(rancher): add rate limit and error pages labels.
This commit is contained in:
parent
d0a6689413
commit
22405a1259
3 changed files with 186 additions and 18 deletions
|
@ -15,17 +15,12 @@ import (
|
||||||
func (p *Provider) buildConfiguration(services []rancherData) *types.Configuration {
|
func (p *Provider) buildConfiguration(services []rancherData) *types.Configuration {
|
||||||
|
|
||||||
var RancherFuncMap = template.FuncMap{
|
var RancherFuncMap = template.FuncMap{
|
||||||
|
"getDomain": getFuncString(label.TraefikDomain, p.Domain), // FIXME dead ?
|
||||||
|
|
||||||
|
// Backend functions
|
||||||
"getPort": getFuncString(label.TraefikPort, ""),
|
"getPort": getFuncString(label.TraefikPort, ""),
|
||||||
"getBackend": getBackend,
|
|
||||||
"getWeight": getFuncString(label.TraefikWeight, label.DefaultWeight),
|
|
||||||
"getDomain": getFuncString(label.TraefikDomain, p.Domain),
|
|
||||||
"getProtocol": getFuncString(label.TraefikProtocol, label.DefaultProtocol),
|
"getProtocol": getFuncString(label.TraefikProtocol, label.DefaultProtocol),
|
||||||
"getPassHostHeader": getFuncString(label.TraefikFrontendPassHostHeader, label.DefaultPassHostHeader),
|
"getWeight": getFuncString(label.TraefikWeight, label.DefaultWeight),
|
||||||
"getPassTLSCert": getFuncBool(label.TraefikFrontendPassTLSCert, label.DefaultPassTLSCert),
|
|
||||||
"getPriority": getFuncString(label.TraefikFrontendPriority, label.DefaultFrontendPriority),
|
|
||||||
"getEntryPoints": getFuncSliceString(label.TraefikFrontendEntryPoints),
|
|
||||||
"getBasicAuth": getFuncSliceString(label.TraefikFrontendAuthBasic),
|
|
||||||
"getFrontendRule": p.getFrontendRule,
|
|
||||||
"hasCircuitBreakerLabel": hasFunc(label.TraefikBackendCircuitBreakerExpression),
|
"hasCircuitBreakerLabel": hasFunc(label.TraefikBackendCircuitBreakerExpression),
|
||||||
"getCircuitBreakerExpression": getFuncString(label.TraefikBackendCircuitBreakerExpression, label.DefaultCircuitBreakerExpression),
|
"getCircuitBreakerExpression": getFuncString(label.TraefikBackendCircuitBreakerExpression, label.DefaultCircuitBreakerExpression),
|
||||||
"hasLoadBalancerLabel": hasLoadBalancerLabel,
|
"hasLoadBalancerLabel": hasLoadBalancerLabel,
|
||||||
|
@ -33,19 +28,33 @@ func (p *Provider) buildConfiguration(services []rancherData) *types.Configurati
|
||||||
"hasMaxConnLabels": hasMaxConnLabels,
|
"hasMaxConnLabels": hasMaxConnLabels,
|
||||||
"getMaxConnAmount": getFuncInt64(label.TraefikBackendMaxConnAmount, math.MaxInt64),
|
"getMaxConnAmount": getFuncInt64(label.TraefikBackendMaxConnAmount, math.MaxInt64),
|
||||||
"getMaxConnExtractorFunc": getFuncString(label.TraefikBackendMaxConnExtractorFunc, label.DefaultBackendMaxconnExtractorFunc),
|
"getMaxConnExtractorFunc": getFuncString(label.TraefikBackendMaxConnExtractorFunc, label.DefaultBackendMaxconnExtractorFunc),
|
||||||
"getSticky": getSticky, // deprecated
|
"getSticky": getSticky,
|
||||||
"hasStickinessLabel": hasFunc(label.TraefikBackendLoadBalancerStickiness),
|
"hasStickinessLabel": hasFunc(label.TraefikBackendLoadBalancerStickiness),
|
||||||
"getStickinessCookieName": getFuncString(label.TraefikBackendLoadBalancerStickinessCookieName, label.DefaultBackendLoadbalancerStickinessCookieName),
|
"getStickinessCookieName": getFuncString(label.TraefikBackendLoadBalancerStickinessCookieName, label.DefaultBackendLoadbalancerStickinessCookieName),
|
||||||
"hasRedirect": hasRedirect,
|
|
||||||
"getRedirectEntryPoint": getFuncString(label.TraefikFrontendRedirectEntryPoint, label.DefaultFrontendRedirectEntryPoint),
|
|
||||||
"getRedirectRegex": getFuncString(label.TraefikFrontendRedirectRegex, ""),
|
|
||||||
"getRedirectReplacement": getFuncString(label.TraefikFrontendRedirectReplacement, ""),
|
|
||||||
"getWhitelistSourceRange": getFuncSliceString(label.TraefikFrontendWhitelistSourceRange),
|
|
||||||
"hasHealthCheckLabels": hasFunc(label.TraefikBackendHealthCheckPath),
|
"hasHealthCheckLabels": hasFunc(label.TraefikBackendHealthCheckPath),
|
||||||
"getHealthCheckPath": getFuncString(label.TraefikBackendHealthCheckPath, ""),
|
"getHealthCheckPath": getFuncString(label.TraefikBackendHealthCheckPath, ""),
|
||||||
"getHealthCheckPort": getFuncInt(label.TraefikBackendHealthCheckPort, label.DefaultBackendHealthCheckPort),
|
"getHealthCheckPort": getFuncInt(label.TraefikBackendHealthCheckPort, label.DefaultBackendHealthCheckPort),
|
||||||
"getHealthCheckInterval": getFuncString(label.TraefikBackendHealthCheckInterval, ""),
|
"getHealthCheckInterval": getFuncString(label.TraefikBackendHealthCheckInterval, ""),
|
||||||
|
|
||||||
|
// Frontend functions
|
||||||
|
"getBackend": getBackend,
|
||||||
|
"getPriority": getFuncString(label.TraefikFrontendPriority, label.DefaultFrontendPriority),
|
||||||
|
"getPassHostHeader": getFuncString(label.TraefikFrontendPassHostHeader, label.DefaultPassHostHeader),
|
||||||
|
"getPassTLSCert": getFuncBool(label.TraefikFrontendPassTLSCert, label.DefaultPassTLSCert),
|
||||||
|
"getEntryPoints": getFuncSliceString(label.TraefikFrontendEntryPoints),
|
||||||
|
"getBasicAuth": getFuncSliceString(label.TraefikFrontendAuthBasic),
|
||||||
|
"getWhitelistSourceRange": getFuncSliceString(label.TraefikFrontendWhitelistSourceRange),
|
||||||
|
"getFrontendRule": p.getFrontendRule,
|
||||||
|
"hasRedirect": hasRedirect,
|
||||||
|
"getRedirectEntryPoint": getFuncString(label.TraefikFrontendRedirectEntryPoint, label.DefaultFrontendRedirectEntryPoint),
|
||||||
|
"getRedirectRegex": getFuncString(label.TraefikFrontendRedirectRegex, ""),
|
||||||
|
"getRedirectReplacement": getFuncString(label.TraefikFrontendRedirectReplacement, ""),
|
||||||
|
"hasErrorPages": hasPrefixFunc(label.Prefix + label.BaseFrontendErrorPage),
|
||||||
|
"getErrorPages": getErrorPages,
|
||||||
|
"hasRateLimits": hasFunc(label.TraefikFrontendRateLimitExtractorFunc),
|
||||||
|
"getRateLimitsExtractorFunc": getFuncString(label.TraefikFrontendRateLimitExtractorFunc, ""),
|
||||||
|
"getRateLimits": getRateLimits,
|
||||||
|
// Headers
|
||||||
"hasRequestHeaders": hasFunc(label.TraefikFrontendRequestHeaders),
|
"hasRequestHeaders": hasFunc(label.TraefikFrontendRequestHeaders),
|
||||||
"getRequestHeaders": getFuncMap(label.TraefikFrontendRequestHeaders),
|
"getRequestHeaders": getFuncMap(label.TraefikFrontendRequestHeaders),
|
||||||
"hasResponseHeaders": hasFunc(label.TraefikFrontendResponseHeaders),
|
"hasResponseHeaders": hasFunc(label.TraefikFrontendResponseHeaders),
|
||||||
|
@ -195,8 +204,21 @@ func getBackend(service rancherData) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasRedirect(service rancherData) bool {
|
func hasRedirect(service rancherData) bool {
|
||||||
return label.Has(service.Labels, label.TraefikFrontendRedirectEntryPoint) ||
|
frep := label.Has(service.Labels, label.TraefikFrontendRedirectEntryPoint)
|
||||||
label.Has(service.Labels, label.TraefikFrontendRedirectRegex) && label.Has(service.Labels, label.TraefikFrontendRedirectReplacement)
|
frrg := label.Has(service.Labels, label.TraefikFrontendRedirectRegex)
|
||||||
|
frrp := label.Has(service.Labels, label.TraefikFrontendRedirectReplacement)
|
||||||
|
|
||||||
|
return frep || frrg && frrp
|
||||||
|
}
|
||||||
|
|
||||||
|
func getErrorPages(service rancherData) map[string]*types.ErrorPage {
|
||||||
|
prefix := label.Prefix + label.BaseFrontendErrorPage
|
||||||
|
return label.ParseErrorPages(service.Labels, prefix, label.RegexpFrontendErrorPage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRateLimits(service rancherData) map[string]*types.Rate {
|
||||||
|
prefix := label.Prefix + label.BaseFrontendRateLimit
|
||||||
|
return label.ParseRateSets(service.Labels, prefix, label.RegexpFrontendRateLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Label functions
|
// Label functions
|
||||||
|
@ -242,3 +264,9 @@ func hasFunc(labelName string) func(service rancherData) bool {
|
||||||
return label.Has(service.Labels, labelName)
|
return label.Has(service.Labels, labelName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hasPrefixFunc(prefix string) func(service rancherData) bool {
|
||||||
|
return func(service rancherData) bool {
|
||||||
|
return label.HasPrefix(service.Labels, prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ package rancher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containous/flaeg"
|
||||||
"github.com/containous/traefik/provider/label"
|
"github.com/containous/traefik/provider/label"
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -70,6 +72,118 @@ func TestProviderBuildConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "with Error Pages",
|
||||||
|
services: []rancherData{
|
||||||
|
{
|
||||||
|
Name: "test/service",
|
||||||
|
Labels: map[string]string{
|
||||||
|
label.TraefikPort: "80",
|
||||||
|
label.Prefix + label.BaseFrontendErrorPage + "foo." + label.SuffixErrorPageStatus: "404",
|
||||||
|
label.Prefix + label.BaseFrontendErrorPage + "foo." + label.SuffixErrorPageBackend: "foobar",
|
||||||
|
label.Prefix + label.BaseFrontendErrorPage + "foo." + label.SuffixErrorPageQuery: "foo_query",
|
||||||
|
label.Prefix + label.BaseFrontendErrorPage + "bar." + label.SuffixErrorPageStatus: "500,600",
|
||||||
|
label.Prefix + label.BaseFrontendErrorPage + "bar." + label.SuffixErrorPageBackend: "foobar",
|
||||||
|
label.Prefix + label.BaseFrontendErrorPage + "bar." + label.SuffixErrorPageQuery: "bar_query",
|
||||||
|
},
|
||||||
|
Health: "healthy",
|
||||||
|
Containers: []string{"127.0.0.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedBackends: map[string]*types.Backend{
|
||||||
|
"backend-test-service": {
|
||||||
|
Servers: map[string]types.Server{
|
||||||
|
"server-0": {
|
||||||
|
URL: "http://127.0.0.1:80",
|
||||||
|
Weight: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFrontends: map[string]*types.Frontend{
|
||||||
|
"frontend-Host-test-service-rancher-localhost": {
|
||||||
|
EntryPoints: []string{},
|
||||||
|
BasicAuth: []string{},
|
||||||
|
Backend: "backend-test-service",
|
||||||
|
Routes: map[string]types.Route{
|
||||||
|
"route-frontend-Host-test-service-rancher-localhost": {
|
||||||
|
Rule: "Host:test.service.rancher.localhost",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PassHostHeader: true,
|
||||||
|
Errors: map[string]*types.ErrorPage{
|
||||||
|
"foo": {
|
||||||
|
Status: []string{"404"},
|
||||||
|
Query: "foo_query",
|
||||||
|
Backend: "foobar",
|
||||||
|
},
|
||||||
|
"bar": {
|
||||||
|
Status: []string{"500", "600"},
|
||||||
|
Query: "bar_query",
|
||||||
|
Backend: "foobar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "with rate Limits",
|
||||||
|
services: []rancherData{
|
||||||
|
{
|
||||||
|
Name: "test/service",
|
||||||
|
Labels: map[string]string{
|
||||||
|
label.TraefikPort: "80",
|
||||||
|
label.TraefikFrontendRateLimitExtractorFunc: "client.ip",
|
||||||
|
label.Prefix + label.BaseFrontendRateLimit + "foo." + label.SuffixRateLimitPeriod: "6",
|
||||||
|
label.Prefix + label.BaseFrontendRateLimit + "foo." + label.SuffixRateLimitAverage: "12",
|
||||||
|
label.Prefix + label.BaseFrontendRateLimit + "foo." + label.SuffixRateLimitBurst: "18",
|
||||||
|
label.Prefix + label.BaseFrontendRateLimit + "bar." + label.SuffixRateLimitPeriod: "3",
|
||||||
|
label.Prefix + label.BaseFrontendRateLimit + "bar." + label.SuffixRateLimitAverage: "6",
|
||||||
|
label.Prefix + label.BaseFrontendRateLimit + "bar." + label.SuffixRateLimitBurst: "9",
|
||||||
|
},
|
||||||
|
Health: "healthy",
|
||||||
|
Containers: []string{"127.0.0.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedBackends: map[string]*types.Backend{
|
||||||
|
"backend-test-service": {
|
||||||
|
Servers: map[string]types.Server{
|
||||||
|
"server-0": {
|
||||||
|
URL: "http://127.0.0.1:80",
|
||||||
|
Weight: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFrontends: map[string]*types.Frontend{
|
||||||
|
"frontend-Host-test-service-rancher-localhost": {
|
||||||
|
EntryPoints: []string{},
|
||||||
|
BasicAuth: []string{},
|
||||||
|
Backend: "backend-test-service",
|
||||||
|
Routes: map[string]types.Route{
|
||||||
|
"route-frontend-Host-test-service-rancher-localhost": {
|
||||||
|
Rule: "Host:test.service.rancher.localhost",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PassHostHeader: true,
|
||||||
|
RateLimit: &types.RateLimit{
|
||||||
|
ExtractorFunc: "client.ip",
|
||||||
|
RateSet: map[string]*types.Rate{
|
||||||
|
"foo": {
|
||||||
|
Period: flaeg.Duration(6 * time.Second),
|
||||||
|
Average: 12,
|
||||||
|
Burst: 18,
|
||||||
|
},
|
||||||
|
"bar": {
|
||||||
|
Period: flaeg.Duration(3 * time.Second),
|
||||||
|
Average: 6,
|
||||||
|
Burst: 9,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
[backends]
|
[backends]
|
||||||
{{range $backendName, $backend := .Backends}}
|
{{range $backendName, $backend := .Backends}}
|
||||||
|
|
||||||
|
[backends.backend-{{$backendName}}]
|
||||||
|
|
||||||
{{if hasCircuitBreakerLabel $backend}}
|
{{if hasCircuitBreakerLabel $backend}}
|
||||||
[backends.backend-{{$backendName}}.circuitBreaker]
|
[backends.backend-{{$backendName}}.circuitBreaker]
|
||||||
expression = "{{getCircuitBreakerExpression $backend}}"
|
expression = "{{getCircuitBreakerExpression $backend}}"
|
||||||
|
@ -68,7 +70,31 @@
|
||||||
replacement = "{{getRedirectReplacement $service}}"
|
replacement = "{{getRedirectReplacement $service}}"
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
[frontends."frontend-{{$frontendName}}".headers]
|
{{ if hasErrorPages $service }}
|
||||||
|
[frontends."frontend-{{$frontendName}}".errors]
|
||||||
|
{{ range $pageName, $page := getErrorPages $service }}
|
||||||
|
[frontends."frontend-{{$frontendName}}".errors.{{ $pageName }}]
|
||||||
|
status = [{{range $page.Status}}
|
||||||
|
"{{.}}",
|
||||||
|
{{end}}]
|
||||||
|
backend = "{{$page.Backend}}"
|
||||||
|
query = "{{$page.Query}}"
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{ if hasRateLimits $service }}
|
||||||
|
[frontends."frontend-{{$frontendName}}".rateLimit]
|
||||||
|
extractorFunc = "{{ getRateLimitsExtractorFunc $service }}"
|
||||||
|
[frontends."frontend-{{$frontendName}}".rateLimit.rateSet]
|
||||||
|
{{ range $limitName, $rateLimit := getRateLimits $service }}
|
||||||
|
[frontends."frontend-{{$frontendName}}".rateLimit.rateSet.{{ $limitName }}]
|
||||||
|
period = "{{ $rateLimit.Period }}"
|
||||||
|
average = {{ $rateLimit.Average }}
|
||||||
|
burst = {{ $rateLimit.Burst }}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
[frontends."frontend-{{$frontendName}}".headers]
|
||||||
{{if hasSSLRedirectHeaders $service}}
|
{{if hasSSLRedirectHeaders $service}}
|
||||||
SSLRedirect = {{getSSLRedirectHeaders $service}}
|
SSLRedirect = {{getSSLRedirectHeaders $service}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
Loading…
Add table
Reference in a new issue