feat(docker): add rate limit labels.
This commit is contained in:
parent
c30ebe5f90
commit
942614dd23
8 changed files with 226 additions and 16 deletions
|
@ -37,20 +37,23 @@ func (p *Provider) buildConfiguration(containersInspected []dockerData) *types.C
|
||||||
"getStickinessCookieName": getFuncStringLabel(label.TraefikBackendLoadBalancerStickinessCookieName, label.DefaultBackendLoadbalancerStickinessCookieName),
|
"getStickinessCookieName": getFuncStringLabel(label.TraefikBackendLoadBalancerStickinessCookieName, label.DefaultBackendLoadbalancerStickinessCookieName),
|
||||||
|
|
||||||
// Frontend functions
|
// Frontend functions
|
||||||
"getBackend": getBackend,
|
"getBackend": getBackend,
|
||||||
"getPriority": getFuncStringLabel(label.TraefikFrontendPriority, label.DefaultFrontendPriority),
|
"getPriority": getFuncStringLabel(label.TraefikFrontendPriority, label.DefaultFrontendPriority),
|
||||||
"getPassHostHeader": getFuncStringLabel(label.TraefikFrontendPassHostHeader, label.DefaultPassHostHeader),
|
"getPassHostHeader": getFuncStringLabel(label.TraefikFrontendPassHostHeader, label.DefaultPassHostHeader),
|
||||||
"getPassTLSCert": getFuncBoolLabel(label.TraefikFrontendPassTLSCert, label.DefaultPassTLSCert),
|
"getPassTLSCert": getFuncBoolLabel(label.TraefikFrontendPassTLSCert, label.DefaultPassTLSCert),
|
||||||
"getEntryPoints": getFuncSliceStringLabel(label.TraefikFrontendEntryPoints),
|
"getEntryPoints": getFuncSliceStringLabel(label.TraefikFrontendEntryPoints),
|
||||||
"getBasicAuth": getFuncSliceStringLabel(label.TraefikFrontendAuthBasic),
|
"getBasicAuth": getFuncSliceStringLabel(label.TraefikFrontendAuthBasic),
|
||||||
"getWhitelistSourceRange": getFuncSliceStringLabel(label.TraefikFrontendWhitelistSourceRange),
|
"getWhitelistSourceRange": getFuncSliceStringLabel(label.TraefikFrontendWhitelistSourceRange),
|
||||||
"getFrontendRule": p.getFrontendRule,
|
"getFrontendRule": p.getFrontendRule,
|
||||||
"hasRedirect": hasRedirect,
|
"hasRedirect": hasRedirect,
|
||||||
"getRedirectEntryPoint": getFuncStringLabel(label.TraefikFrontendRedirectEntryPoint, label.DefaultFrontendRedirectEntryPoint),
|
"getRedirectEntryPoint": getFuncStringLabel(label.TraefikFrontendRedirectEntryPoint, label.DefaultFrontendRedirectEntryPoint),
|
||||||
"getRedirectRegex": getFuncStringLabel(label.TraefikFrontendRedirectRegex, ""),
|
"getRedirectRegex": getFuncStringLabel(label.TraefikFrontendRedirectRegex, ""),
|
||||||
"getRedirectReplacement": getFuncStringLabel(label.TraefikFrontendRedirectReplacement, ""),
|
"getRedirectReplacement": getFuncStringLabel(label.TraefikFrontendRedirectReplacement, ""),
|
||||||
"hasErrorPages": hasErrorPages,
|
"hasErrorPages": hasErrorPages,
|
||||||
"getErrorPages": getErrorPages,
|
"getErrorPages": getErrorPages,
|
||||||
|
"hasRateLimits": hasFunc(label.TraefikFrontendRateLimitExtractorFunc),
|
||||||
|
"getRateLimitsExtractorFunc": getFuncStringLabel(label.TraefikFrontendRateLimitExtractorFunc, ""),
|
||||||
|
"getRateLimits": getRateLimits,
|
||||||
// Headers
|
// Headers
|
||||||
"hasRequestHeaders": hasFunc(label.TraefikFrontendRequestHeaders),
|
"hasRequestHeaders": hasFunc(label.TraefikFrontendRequestHeaders),
|
||||||
"getRequestHeaders": getFuncMapLabel(label.TraefikFrontendRequestHeaders),
|
"getRequestHeaders": getFuncMapLabel(label.TraefikFrontendRequestHeaders),
|
||||||
|
@ -118,6 +121,8 @@ func (p *Provider) buildConfiguration(containersInspected []dockerData) *types.C
|
||||||
"getServiceResponseHeaders": getFuncServiceMapLabel(label.SuffixFrontendResponseHeaders),
|
"getServiceResponseHeaders": getFuncServiceMapLabel(label.SuffixFrontendResponseHeaders),
|
||||||
"hasServiceErrorPages": hasServiceErrorPages,
|
"hasServiceErrorPages": hasServiceErrorPages,
|
||||||
"getServiceErrorPages": getServiceErrorPages,
|
"getServiceErrorPages": getServiceErrorPages,
|
||||||
|
"hasServiceRateLimits": hasFuncServiceLabel(label.SuffixFrontendRateLimitExtractorFunc),
|
||||||
|
"getServiceRateLimits": getServiceRateLimits,
|
||||||
}
|
}
|
||||||
// filter containers
|
// filter containers
|
||||||
filteredContainers := fun.Filter(func(container dockerData) bool {
|
filteredContainers := fun.Filter(func(container dockerData) bool {
|
||||||
|
|
|
@ -182,6 +182,11 @@ func getErrorPages(container dockerData) map[string]*types.ErrorPage {
|
||||||
return label.ParseErrorPages(container.Labels, prefix, label.RegexpFrontendErrorPage)
|
return label.ParseErrorPages(container.Labels, prefix, label.RegexpFrontendErrorPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getRateLimits(container dockerData) map[string]*types.Rate {
|
||||||
|
prefix := label.Prefix + label.BaseFrontendRateLimit
|
||||||
|
return label.ParseRateSets(container.Labels, prefix, label.RegexpFrontendRateLimit)
|
||||||
|
}
|
||||||
|
|
||||||
// Label functions
|
// Label functions
|
||||||
|
|
||||||
func getFuncInt64Label(labelName string, defaultValue int64) func(container dockerData) int64 {
|
func getFuncInt64Label(labelName string, defaultValue int64) func(container dockerData) int64 {
|
||||||
|
|
|
@ -4,7 +4,9 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"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"
|
||||||
docker "github.com/docker/docker/api/types"
|
docker "github.com/docker/docker/api/types"
|
||||||
|
@ -236,6 +238,65 @@ func TestDockerBuildConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
containers: []docker.ContainerJSON{
|
||||||
|
containerJSON(
|
||||||
|
name("test1"),
|
||||||
|
labels(map[string]string{
|
||||||
|
label.TraefikBackend: "foobar",
|
||||||
|
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",
|
||||||
|
}),
|
||||||
|
ports(nat.PortMap{
|
||||||
|
"80/tcp": {},
|
||||||
|
}),
|
||||||
|
withNetwork("bridge", ipv4("127.0.0.1")),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expectedFrontends: map[string]*types.Frontend{
|
||||||
|
"frontend-Host-test1-docker-localhost-0": {
|
||||||
|
EntryPoints: []string{},
|
||||||
|
BasicAuth: []string{},
|
||||||
|
PassHostHeader: true,
|
||||||
|
Backend: "backend-foobar",
|
||||||
|
Routes: map[string]types.Route{
|
||||||
|
"route-frontend-Host-test1-docker-localhost-0": {
|
||||||
|
Rule: "Host:test1.docker.localhost",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedBackends: map[string]*types.Backend{
|
||||||
|
"backend-foobar": {
|
||||||
|
Servers: map[string]types.Server{
|
||||||
|
"server-test1": {
|
||||||
|
URL: "http://127.0.0.1:80",
|
||||||
|
Weight: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for caseID, test := range testCases {
|
for caseID, test := range testCases {
|
||||||
|
|
|
@ -108,6 +108,11 @@ func getServiceErrorPages(container dockerData, serviceName string) map[string]*
|
||||||
return label.ParseErrorPages(serviceLabels, label.BaseFrontendErrorPage, label.RegexpBaseFrontendErrorPage)
|
return label.ParseErrorPages(serviceLabels, label.BaseFrontendErrorPage, label.RegexpBaseFrontendErrorPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getServiceRateLimits(container dockerData, serviceName string) map[string]*types.Rate {
|
||||||
|
serviceLabels := getServiceLabels(container, serviceName)
|
||||||
|
return label.ParseRateSets(serviceLabels, label.BaseFrontendRateLimit, label.RegexpBaseFrontendRateLimit)
|
||||||
|
}
|
||||||
|
|
||||||
// Service label functions
|
// Service label functions
|
||||||
|
|
||||||
func getFuncServiceMapLabel(labelSuffix string) func(container dockerData, serviceName string) map[string]string {
|
func getFuncServiceMapLabel(labelSuffix string) func(container dockerData, serviceName string) map[string]string {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containous/flaeg"
|
||||||
"github.com/containous/traefik/log"
|
"github.com/containous/traefik/log"
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
)
|
)
|
||||||
|
@ -44,6 +45,12 @@ var (
|
||||||
|
|
||||||
// RegexpFrontendErrorPage used to extract error pages from label
|
// RegexpFrontendErrorPage used to extract error pages from label
|
||||||
RegexpFrontendErrorPage = regexp.MustCompile(`^traefik\.frontend\.errors\.(?P<name>[^ .]+)\.(?P<field>[^ .]+)$`)
|
RegexpFrontendErrorPage = regexp.MustCompile(`^traefik\.frontend\.errors\.(?P<name>[^ .]+)\.(?P<field>[^ .]+)$`)
|
||||||
|
|
||||||
|
// RegexpBaseFrontendRateLimit used to extract rate limits from service's label
|
||||||
|
RegexpBaseFrontendRateLimit = regexp.MustCompile(`^frontend\.rateLimit\.rateSet\.(?P<name>[^ .]+)\.(?P<field>[^ .]+)$`)
|
||||||
|
|
||||||
|
// RegexpFrontendRateLimit used to extract rate limits from label
|
||||||
|
RegexpFrontendRateLimit = regexp.MustCompile(`^traefik\.frontend\.rateLimit\.rateSet\.(?P<name>[^ .]+)\.(?P<field>[^ .]+)$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServicePropertyValues is a map of services properties
|
// ServicePropertyValues is a map of services properties
|
||||||
|
@ -295,6 +302,58 @@ func ParseErrorPages(labels map[string]string, labelPrefix string, labelRegex *r
|
||||||
return errorPages
|
return errorPages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseRateSets parse rate limits to create Rate struct
|
||||||
|
func ParseRateSets(labels map[string]string, labelPrefix string, labelRegex *regexp.Regexp) map[string]*types.Rate {
|
||||||
|
rateSets := make(map[string]*types.Rate)
|
||||||
|
|
||||||
|
for lblName, rawValue := range labels {
|
||||||
|
if strings.HasPrefix(lblName, labelPrefix) && len(rawValue) > 0 {
|
||||||
|
submatch := labelRegex.FindStringSubmatch(lblName)
|
||||||
|
if len(submatch) != 3 {
|
||||||
|
log.Errorf("Invalid rate limit label: %s, sub-match: %v", lblName, submatch)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
limitName := submatch[1]
|
||||||
|
|
||||||
|
ep, ok := rateSets[limitName]
|
||||||
|
if !ok {
|
||||||
|
ep = &types.Rate{}
|
||||||
|
rateSets[limitName] = ep
|
||||||
|
}
|
||||||
|
|
||||||
|
switch submatch[2] {
|
||||||
|
case "period":
|
||||||
|
var d flaeg.Duration
|
||||||
|
err := d.Set(rawValue)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Unable to parse %q: %q. %v", lblName, rawValue, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ep.Period = d
|
||||||
|
case "average":
|
||||||
|
value, err := strconv.ParseInt(rawValue, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Unable to parse %q: %q. %v", lblName, rawValue, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ep.Average = value
|
||||||
|
case "burst":
|
||||||
|
value, err := strconv.ParseInt(rawValue, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Unable to parse %q: %q. %v", lblName, rawValue, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ep.Burst = value
|
||||||
|
default:
|
||||||
|
log.Errorf("Invalid rate limit label: %s", lblName)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rateSets
|
||||||
|
}
|
||||||
|
|
||||||
// IsEnabled Check if a container is enabled in Træfik
|
// IsEnabled Check if a container is enabled in Træfik
|
||||||
func IsEnabled(labels map[string]string, exposedByDefault bool) bool {
|
func IsEnabled(labels map[string]string, exposedByDefault bool) bool {
|
||||||
return GetBoolValue(labels, TraefikEnable, exposedByDefault)
|
return GetBoolValue(labels, TraefikEnable, exposedByDefault)
|
||||||
|
|
|
@ -2,7 +2,9 @@ package label
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containous/flaeg"
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
@ -1081,3 +1083,46 @@ func TestParseErrorPages(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseRateSets(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
labels map[string]string
|
||||||
|
expected map[string]*types.Rate
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "2 rate limits",
|
||||||
|
labels: map[string]string{
|
||||||
|
Prefix + BaseFrontendRateLimit + "foo." + SuffixRateLimitPeriod: "6",
|
||||||
|
Prefix + BaseFrontendRateLimit + "foo." + SuffixRateLimitAverage: "12",
|
||||||
|
Prefix + BaseFrontendRateLimit + "foo." + SuffixRateLimitBurst: "18",
|
||||||
|
Prefix + BaseFrontendRateLimit + "bar." + SuffixRateLimitPeriod: "3",
|
||||||
|
Prefix + BaseFrontendRateLimit + "bar." + SuffixRateLimitAverage: "6",
|
||||||
|
Prefix + BaseFrontendRateLimit + "bar." + SuffixRateLimitBurst: "9",
|
||||||
|
},
|
||||||
|
expected: 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 {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
rateSets := ParseRateSets(test.labels, Prefix+BaseFrontendRateLimit, RegexpFrontendRateLimit)
|
||||||
|
|
||||||
|
assert.EqualValues(t, test.expected, rateSets)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ const (
|
||||||
SuffixFrontendPassHostHeader = "frontend.passHostHeader"
|
SuffixFrontendPassHostHeader = "frontend.passHostHeader"
|
||||||
SuffixFrontendPassTLSCert = "frontend.passTLSCert"
|
SuffixFrontendPassTLSCert = "frontend.passTLSCert"
|
||||||
SuffixFrontendPriority = "frontend.priority"
|
SuffixFrontendPriority = "frontend.priority"
|
||||||
|
SuffixFrontendRateLimitExtractorFunc = "frontend.rateLimit.extractorFunc"
|
||||||
SuffixFrontendRedirectEntryPoint = "frontend.redirect.entryPoint"
|
SuffixFrontendRedirectEntryPoint = "frontend.redirect.entryPoint"
|
||||||
SuffixFrontendRedirectRegex = "frontend.redirect.regex"
|
SuffixFrontendRedirectRegex = "frontend.redirect.regex"
|
||||||
SuffixFrontendRedirectReplacement = "frontend.redirect.replacement"
|
SuffixFrontendRedirectReplacement = "frontend.redirect.replacement"
|
||||||
|
@ -83,11 +84,12 @@ const (
|
||||||
TraefikFrontendPassHostHeader = Prefix + SuffixFrontendPassHostHeader
|
TraefikFrontendPassHostHeader = Prefix + SuffixFrontendPassHostHeader
|
||||||
TraefikFrontendPassTLSCert = Prefix + SuffixFrontendPassTLSCert
|
TraefikFrontendPassTLSCert = Prefix + SuffixFrontendPassTLSCert
|
||||||
TraefikFrontendPriority = Prefix + SuffixFrontendPriority
|
TraefikFrontendPriority = Prefix + SuffixFrontendPriority
|
||||||
TraefikFrontendRule = Prefix + SuffixFrontendRule
|
TraefikFrontendRateLimitExtractorFunc = Prefix + SuffixFrontendRateLimitExtractorFunc
|
||||||
TraefikFrontendRuleType = Prefix + SuffixFrontendRuleType
|
|
||||||
TraefikFrontendRedirectEntryPoint = Prefix + SuffixFrontendRedirectEntryPoint
|
TraefikFrontendRedirectEntryPoint = Prefix + SuffixFrontendRedirectEntryPoint
|
||||||
TraefikFrontendRedirectRegex = Prefix + SuffixFrontendRedirectRegex
|
TraefikFrontendRedirectRegex = Prefix + SuffixFrontendRedirectRegex
|
||||||
TraefikFrontendRedirectReplacement = Prefix + SuffixFrontendRedirectReplacement
|
TraefikFrontendRedirectReplacement = Prefix + SuffixFrontendRedirectReplacement
|
||||||
|
TraefikFrontendRule = Prefix + SuffixFrontendRule
|
||||||
|
TraefikFrontendRuleType = Prefix + SuffixFrontendRuleType
|
||||||
TraefikFrontendValue = Prefix + SuffixFrontendValue
|
TraefikFrontendValue = Prefix + SuffixFrontendValue
|
||||||
TraefikFrontendWhitelistSourceRange = Prefix + SuffixFrontendWhitelistSourceRange
|
TraefikFrontendWhitelistSourceRange = Prefix + SuffixFrontendWhitelistSourceRange
|
||||||
TraefikFrontendRequestHeaders = Prefix + SuffixFrontendRequestHeaders
|
TraefikFrontendRequestHeaders = Prefix + SuffixFrontendRequestHeaders
|
||||||
|
@ -114,4 +116,8 @@ const (
|
||||||
SuffixErrorPageBackend = "backend"
|
SuffixErrorPageBackend = "backend"
|
||||||
SuffixErrorPageQuery = "query"
|
SuffixErrorPageQuery = "query"
|
||||||
SuffixErrorPageStatus = "status"
|
SuffixErrorPageStatus = "status"
|
||||||
|
BaseFrontendRateLimit = "frontend.rateLimit.rateSet."
|
||||||
|
SuffixRateLimitPeriod = "period"
|
||||||
|
SuffixRateLimitAverage = "average"
|
||||||
|
SuffixRateLimitBurst = "burst"
|
||||||
)
|
)
|
||||||
|
|
|
@ -95,6 +95,18 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
{{ if hasServiceRateLimits $container $serviceName }}
|
||||||
|
[frontends."frontend-{{getServiceBackend $container $serviceName}}".rateLimit]
|
||||||
|
extractorFunc = "{{ getRateLimitsExtractorFunc $container $serviceName }}"
|
||||||
|
[frontends."frontend-{{getServiceBackend $container $serviceName}}".rateLimit.rateSet]
|
||||||
|
{{ range $limitName, $rateLimit := getServiceRateLimits $container $serviceName }}
|
||||||
|
[frontends."frontend-{{getServiceBackend $container $serviceName}}".rateLimit.rateSet.{{ $limitName }}]
|
||||||
|
period = "{{ $rateLimit.Period }}"
|
||||||
|
average = {{ $rateLimit.Average }}
|
||||||
|
burst = {{ $rateLimit.Burst }}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
[frontends."frontend-{{getServiceBackend $container $serviceName}}".routes."service-{{$serviceName | replace "/" "" | replace "." "-"}}"]
|
[frontends."frontend-{{getServiceBackend $container $serviceName}}".routes."service-{{$serviceName | replace "/" "" | replace "." "-"}}"]
|
||||||
rule = "{{getServiceFrontendRule $container $serviceName}}"
|
rule = "{{getServiceFrontendRule $container $serviceName}}"
|
||||||
|
|
||||||
|
@ -155,6 +167,18 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
{{ if hasRateLimits $container }}
|
||||||
|
[frontends."frontend-{{$frontend}}".rateLimit]
|
||||||
|
extractorFunc = "{{ getRateLimitsExtractorFunc $container }}"
|
||||||
|
[frontends."frontend-{{$frontend}}".rateLimit.rateSet]
|
||||||
|
{{ range $limitName, $rateLimit := getRateLimits $container }}
|
||||||
|
[frontends."frontend-{{$frontend}}".rateLimit.rateSet.{{ $limitName }}]
|
||||||
|
period = "{{ $rateLimit.Period }}"
|
||||||
|
average = {{ $rateLimit.Average }}
|
||||||
|
burst = {{ $rateLimit.Burst }}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
[frontends."frontend-{{$frontend}}".headers]
|
[frontends."frontend-{{$frontend}}".headers]
|
||||||
{{if hasSSLRedirectHeaders $container}}
|
{{if hasSSLRedirectHeaders $container}}
|
||||||
SSLRedirect = {{getSSLRedirectHeaders $container}}
|
SSLRedirect = {{getSSLRedirectHeaders $container}}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue