feat(ecs): add error pages and rate limits.

This commit is contained in:
Fernandez Ludovic 2017-12-20 22:59:57 +01:00 committed by Traefiker
parent 5acee9e11d
commit 393651f5e2
2 changed files with 133 additions and 65 deletions

View file

@ -36,18 +36,23 @@ func (p *Provider) buildConfiguration(services map[string][]ecsInstance) (*types
"getMaxConnExtractorFunc": getFuncFirstStringValue(label.TraefikBackendMaxConnExtractorFunc, label.DefaultBackendMaxconnExtractorFunc), "getMaxConnExtractorFunc": getFuncFirstStringValue(label.TraefikBackendMaxConnExtractorFunc, label.DefaultBackendMaxconnExtractorFunc),
// Frontend functions // Frontend functions
"filterFrontends": filterFrontends, "filterFrontends": filterFrontends,
"getFrontendRule": p.getFrontendRule, "getFrontendRule": p.getFrontendRule,
"getPassHostHeader": getFuncStringValue(label.TraefikFrontendPassHostHeader, label.DefaultPassHostHeader), "getPassHostHeader": getFuncStringValue(label.TraefikFrontendPassHostHeader, label.DefaultPassHostHeader),
"getPassTLSCert": getFuncBoolValue(label.TraefikFrontendPassTLSCert, label.DefaultPassTLSCert), "getPassTLSCert": getFuncBoolValue(label.TraefikFrontendPassTLSCert, label.DefaultPassTLSCert),
"getPriority": getFuncStringValue(label.TraefikFrontendPriority, label.DefaultFrontendPriority), "getPriority": getFuncStringValue(label.TraefikFrontendPriority, label.DefaultFrontendPriority),
"getBasicAuth": getFuncSliceString(label.TraefikFrontendAuthBasic), "getBasicAuth": getFuncSliceString(label.TraefikFrontendAuthBasic),
"getEntryPoints": getFuncSliceString(label.TraefikFrontendEntryPoints), "getEntryPoints": getFuncSliceString(label.TraefikFrontendEntryPoints),
"getWhitelistSourceRange": getFuncSliceString(label.TraefikFrontendWhitelistSourceRange), "getWhitelistSourceRange": getFuncSliceString(label.TraefikFrontendWhitelistSourceRange),
"hasRedirect": hasRedirect, "hasRedirect": hasRedirect,
"getRedirectEntryPoint": getFuncStringValue(label.TraefikFrontendRedirectEntryPoint, label.DefaultFrontendRedirectEntryPoint), "getRedirectEntryPoint": getFuncStringValue(label.TraefikFrontendRedirectEntryPoint, label.DefaultFrontendRedirectEntryPoint),
"getRedirectRegex": getFuncStringValue(label.TraefikFrontendRedirectRegex, ""), "getRedirectRegex": getFuncStringValue(label.TraefikFrontendRedirectRegex, ""),
"getRedirectReplacement": getFuncStringValue(label.TraefikFrontendRedirectReplacement, ""), "getRedirectReplacement": getFuncStringValue(label.TraefikFrontendRedirectReplacement, ""),
"hasErrorPages": hasPrefixFuncLabel(label.Prefix + label.BaseFrontendErrorPage),
"getErrorPages": getErrorPages,
"hasRateLimits": hasFuncLabel(label.TraefikFrontendRateLimitExtractorFunc),
"getRateLimitsExtractorFunc": getFuncStringValue(label.TraefikFrontendRateLimitExtractorFunc, ""),
"getRateLimits": getRateLimits,
// Headers // Headers
"hasRequestHeaders": hasFuncLabel(label.TraefikFrontendRequestHeaders), "hasRequestHeaders": hasFuncLabel(label.TraefikFrontendRequestHeaders),
"getRequestHeaders": getFuncMapValue(label.TraefikFrontendRequestHeaders), "getRequestHeaders": getFuncMapValue(label.TraefikFrontendRequestHeaders),
@ -154,6 +159,20 @@ func hasRedirect(instance ecsInstance) bool {
hasLabel(instance, label.TraefikFrontendRedirectRegex) && hasLabel(instance, label.TraefikFrontendRedirectReplacement) hasLabel(instance, label.TraefikFrontendRedirectRegex) && hasLabel(instance, label.TraefikFrontendRedirectReplacement)
} }
func getErrorPages(instance ecsInstance) map[string]*types.ErrorPage {
labels := mapPToMap(instance.containerDefinition.DockerLabels)
prefix := label.Prefix + label.BaseFrontendErrorPage
return label.ParseErrorPages(labels, prefix, label.RegexpFrontendErrorPage)
}
func getRateLimits(instance ecsInstance) map[string]*types.Rate {
labels := mapPToMap(instance.containerDefinition.DockerLabels)
prefix := label.Prefix + label.BaseFrontendRateLimit
return label.ParseRateSets(labels, prefix, label.RegexpFrontendRateLimit)
}
// Label functions // Label functions
func hasFuncLabel(labelName string) func(i ecsInstance) bool { func hasFuncLabel(labelName string) func(i ecsInstance) bool {
@ -162,6 +181,12 @@ func hasFuncLabel(labelName string) func(i ecsInstance) bool {
} }
} }
func hasPrefixFuncLabel(prefix string) func(i ecsInstance) bool {
return func(i ecsInstance) bool {
return hasPrefix(i, prefix)
}
}
func getFuncStringValue(labelName string, defaultValue string) func(i ecsInstance) string { func getFuncStringValue(labelName string, defaultValue string) func(i ecsInstance) string {
return func(i ecsInstance) string { return func(i ecsInstance) string {
return getStringValue(i, labelName, defaultValue) return getStringValue(i, labelName, defaultValue)
@ -236,6 +261,15 @@ func hasLabel(i ecsInstance, labelName string) bool {
return ok && value != nil && len(*value) > 0 return ok && value != nil && len(*value) > 0
} }
func hasPrefix(i ecsInstance, prefix string) bool {
for name, value := range i.containerDefinition.DockerLabels {
if strings.HasPrefix(name, prefix) && value != nil && len(*value) > 0 {
return true
}
}
return false
}
func getStringValue(i ecsInstance, labelName string, defaultValue string) string { func getStringValue(i ecsInstance, labelName string, defaultValue string) string {
if v, ok := i.containerDefinition.DockerLabels[labelName]; ok { if v, ok := i.containerDefinition.DockerLabels[labelName]; ok {
if v == nil { if v == nil {
@ -328,6 +362,16 @@ func getFirstStringValue(instances []ecsInstance, labelName string, defaultValue
return getStringValue(instances[0], labelName, defaultValue) return getStringValue(instances[0], labelName, defaultValue)
} }
func mapPToMap(src map[string]*string) map[string]string {
result := make(map[string]string)
for key, value := range src {
if value != nil && len(*value) > 0 {
result[key] = *value
}
}
return result
}
func isEnabled(i ecsInstance, exposedByDefault bool) bool { func isEnabled(i ecsInstance, exposedByDefault bool) bool {
return getBoolValue(i, label.TraefikEnable, exposedByDefault) return getBoolValue(i, label.TraefikEnable, exposedByDefault)
} }

View file

@ -39,114 +39,138 @@
[frontends] [frontends]
{{range $serviceName, $instances := .Services}} {{range $serviceName, $instances := .Services}}
{{range filterFrontends $instances}} {{range $instance := filterFrontends $instances}}
[frontends.frontend-{{ $serviceName }}] [frontends.frontend-{{ $serviceName }}]
backend = "backend-{{ $serviceName }}" backend = "backend-{{ $serviceName }}"
priority = {{ getPriority .}} priority = {{ getPriority $instance}}
passHostHeader = {{ getPassHostHeader .}} passHostHeader = {{ getPassHostHeader $instance}}
passTLSCert = {{ getPassTLSCert .}} passTLSCert = {{ getPassTLSCert $instance}}
entryPoints = [{{range getEntryPoints .}} entryPoints = [{{range getEntryPoints $instance}}
"{{.}}", "{{.}}",
{{end}}] {{end}}]
{{if getWhitelistSourceRange .}} {{if getWhitelistSourceRange $instance}}
whitelistSourceRange = [{{range getWhitelistSourceRange .}} whitelistSourceRange = [{{range getWhitelistSourceRange $instance}}
"{{.}}", "{{.}}",
{{end}}] {{end}}]
{{end}} {{end}}
basicAuth = [{{range getBasicAuth .}} basicAuth = [{{range getBasicAuth $instance}}
"{{.}}", "{{.}}",
{{end}}] {{end}}]
{{if hasRedirect .}} {{if hasRedirect $instance}}
[frontends."frontend-{{ $serviceName }}".redirect] [frontends."frontend-{{ $serviceName }}".redirect]
entryPoint = "{{getRedirectEntryPoint .}}" entryPoint = "{{getRedirectEntryPoint $instance}}"
regex = "{{getRedirectRegex .}}" regex = "{{getRedirectRegex $instance}}"
replacement = "{{getRedirectReplacement .}}" replacement = "{{getRedirectReplacement $instance}}"
{{end}}
{{ if hasErrorPages $instance }}
[frontends."frontend-{{ $serviceName }}".errors]
{{ range $pageName, $page := getErrorPages $instance }}
[frontends."frontend-{{ $serviceName }}".errors.{{ $pageName }}]
status = [{{range $page.Status}}
"{{.}}",
{{end}}]
backend = "{{$page.Backend}}"
query = "{{$page.Query}}"
{{end}}
{{end}}
{{ if hasRateLimits $instance }}
[frontends."frontend-{{ $serviceName }}".rateLimit]
extractorFunc = "{{ getRateLimitsExtractorFunc $instance }}"
[frontends."frontend-{{ $serviceName }}".rateLimit.rateSet]
{{ range $limitName, $rateLimit := getRateLimits $instance }}
[frontends."frontend-{{ $serviceName }}".rateLimit.rateSet.{{ $limitName }}]
period = "{{ $rateLimit.Period }}"
average = {{ $rateLimit.Average }}
burst = {{ $rateLimit.Burst }}
{{end}}
{{end}} {{end}}
[frontends."frontend-{{ $serviceName }}".headers] [frontends."frontend-{{ $serviceName }}".headers]
{{if hasSSLRedirectHeaders .}} {{if hasSSLRedirectHeaders $instance}}
SSLRedirect = {{getSSLRedirectHeaders .}} SSLRedirect = {{getSSLRedirectHeaders $instance}}
{{end}} {{end}}
{{if hasSSLTemporaryRedirectHeaders .}} {{if hasSSLTemporaryRedirectHeaders $instance}}
SSLTemporaryRedirect = {{getSSLTemporaryRedirectHeaders .}} SSLTemporaryRedirect = {{getSSLTemporaryRedirectHeaders $instance}}
{{end}} {{end}}
{{if hasSSLHostHeaders .}} {{if hasSSLHostHeaders $instance}}
SSLHost = "{{getSSLHostHeaders .}}" SSLHost = "{{getSSLHostHeaders $instance}}"
{{end}} {{end}}
{{if hasSTSSecondsHeaders .}} {{if hasSTSSecondsHeaders $instance}}
STSSeconds = {{getSTSSecondsHeaders .}} STSSeconds = {{getSTSSecondsHeaders $instance}}
{{end}} {{end}}
{{if hasSTSIncludeSubdomainsHeaders .}} {{if hasSTSIncludeSubdomainsHeaders $instance}}
STSIncludeSubdomains = {{getSTSIncludeSubdomainsHeaders .}} STSIncludeSubdomains = {{getSTSIncludeSubdomainsHeaders $instance}}
{{end}} {{end}}
{{if hasSTSPreloadHeaders .}} {{if hasSTSPreloadHeaders $instance}}
STSPreload = {{getSTSPreloadHeaders .}} STSPreload = {{getSTSPreloadHeaders $instance}}
{{end}} {{end}}
{{if hasForceSTSHeaderHeaders .}} {{if hasForceSTSHeaderHeaders $instance}}
ForceSTSHeader = {{getForceSTSHeaderHeaders .}} ForceSTSHeader = {{getForceSTSHeaderHeaders $instance}}
{{end}} {{end}}
{{if hasFrameDenyHeaders .}} {{if hasFrameDenyHeaders $instance}}
FrameDeny = {{getFrameDenyHeaders .}} FrameDeny = {{getFrameDenyHeaders $instance}}
{{end}} {{end}}
{{if hasCustomFrameOptionsValueHeaders .}} {{if hasCustomFrameOptionsValueHeaders $instance}}
CustomFrameOptionsValue = "{{getCustomFrameOptionsValueHeaders .}}" CustomFrameOptionsValue = "{{getCustomFrameOptionsValueHeaders $instance}}"
{{end}} {{end}}
{{if hasContentTypeNosniffHeaders .}} {{if hasContentTypeNosniffHeaders $instance}}
ContentTypeNosniff = {{getContentTypeNosniffHeaders .}} ContentTypeNosniff = {{getContentTypeNosniffHeaders $instance}}
{{end}} {{end}}
{{if hasBrowserXSSFilterHeaders .}} {{if hasBrowserXSSFilterHeaders $instance}}
BrowserXSSFilter = {{getBrowserXSSFilterHeaders .}} BrowserXSSFilter = {{getBrowserXSSFilterHeaders $instance}}
{{end}} {{end}}
{{if hasContentSecurityPolicyHeaders .}} {{if hasContentSecurityPolicyHeaders $instance}}
ContentSecurityPolicy = "{{getContentSecurityPolicyHeaders .}}" ContentSecurityPolicy = "{{getContentSecurityPolicyHeaders $instance}}"
{{end}} {{end}}
{{if hasPublicKeyHeaders .}} {{if hasPublicKeyHeaders $instance}}
PublicKey = "{{getPublicKeyHeaders .}}" PublicKey = "{{getPublicKeyHeaders $instance}}"
{{end}} {{end}}
{{if hasReferrerPolicyHeaders .}} {{if hasReferrerPolicyHeaders $instance}}
ReferrerPolicy = "{{getReferrerPolicyHeaders .}}" ReferrerPolicy = "{{getReferrerPolicyHeaders $instance}}"
{{end}} {{end}}
{{if hasIsDevelopmentHeaders .}} {{if hasIsDevelopmentHeaders $instance}}
IsDevelopment = {{getIsDevelopmentHeaders .}} IsDevelopment = {{getIsDevelopmentHeaders $instance}}
{{end}} {{end}}
{{if hasRequestHeaders .}} {{if hasRequestHeaders $instance}}
[frontends."frontend-{{ $serviceName }}".headers.customRequestHeaders] [frontends."frontend-{{ $serviceName }}".headers.customRequestHeaders]
{{range $k, $v := getRequestHeaders .}} {{range $k, $v := getRequestHeaders $instance}}
{{$k}} = "{{$v}}" {{$k}} = "{{$v}}"
{{end}} {{end}}
{{end}} {{end}}
{{if hasResponseHeaders .}} {{if hasResponseHeaders $instance}}
[frontends."frontend-{{ $serviceName }}".headers.customResponseHeaders] [frontends."frontend-{{ $serviceName }}".headers.customResponseHeaders]
{{range $k, $v := getResponseHeaders .}} {{range $k, $v := getResponseHeaders $instance}}
{{$k}} = "{{$v}}" {{$k}} = "{{$v}}"
{{end}} {{end}}
{{end}} {{end}}
{{if hasAllowedHostsHeaders .}} {{if hasAllowedHostsHeaders $instance}}
[frontends."frontend-{{ $serviceName }}".headers.AllowedHosts] [frontends."frontend-{{ $serviceName }}".headers.AllowedHosts]
{{range getAllowedHostsHeaders .}} {{range getAllowedHostsHeaders $instance}}
"{{.}}" "{{.}}"
{{end}} {{end}}
{{end}} {{end}}
{{if hasHostsProxyHeaders .}} {{if hasHostsProxyHeaders $instance}}
[frontends."frontend-{{ $serviceName }}".headers.HostsProxyHeaders] [frontends."frontend-{{ $serviceName }}".headers.HostsProxyHeaders]
{{range getHostsProxyHeaders .}} {{range getHostsProxyHeaders $instance}}
"{{.}}" "{{.}}"
{{end}} {{end}}
{{end}} {{end}}
{{if hasSSLProxyHeaders .}} {{if hasSSLProxyHeaders $instance}}
[frontends."frontend-{{ $serviceName }}".headers.SSLProxyHeaders] [frontends."frontend-{{ $serviceName }}".headers.SSLProxyHeaders]
{{range $k, $v := getSSLProxyHeaders .}} {{range $k, $v := getSSLProxyHeaders $instance}}
{{$k}} = "{{$v}}" {{$k}} = "{{$v}}"
{{end}} {{end}}
{{end}} {{end}}
[frontends.frontend-{{ $serviceName }}.routes.route-frontend-{{ $serviceName }}] [frontends.frontend-{{ $serviceName }}.routes.route-frontend-{{ $serviceName }}]
rule = "{{getFrontendRule .}}" rule = "{{getFrontendRule $instance}}"
{{end}} {{end}}
{{end}} {{end}}