Remove blank lines from template rendering
This commit is contained in:
parent
ccaf15cdd4
commit
e603976721
6 changed files with 95 additions and 28 deletions
|
@ -42,6 +42,7 @@ import (
|
||||||
|
|
||||||
"k8s.io/contrib/ingress/controllers/nginx/healthcheck"
|
"k8s.io/contrib/ingress/controllers/nginx/healthcheck"
|
||||||
"k8s.io/contrib/ingress/controllers/nginx/nginx"
|
"k8s.io/contrib/ingress/controllers/nginx/nginx"
|
||||||
|
"k8s.io/contrib/ingress/controllers/nginx/nginx/ratelimit"
|
||||||
"k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite"
|
"k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -583,6 +584,12 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg nginx.NginxConfigur
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rl, err := ratelimit.ParseAnnotations(ing)
|
||||||
|
glog.V(3).Infof("nginx rate limit %v", rl)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(3).Infof("error reading rate limit annotation in Ingress %v/%v: %v", ing.GetNamespace(), ing.GetName(), err)
|
||||||
|
}
|
||||||
|
|
||||||
host := rule.Host
|
host := rule.Host
|
||||||
if host == "" {
|
if host == "" {
|
||||||
host = defServerName
|
host = defServerName
|
||||||
|
@ -615,6 +622,7 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg nginx.NginxConfigur
|
||||||
glog.V(3).Infof("error parsing rewrite annotations for Ingress rule %v/%v: %v", ing.GetNamespace(), ing.GetName(), err)
|
glog.V(3).Infof("error parsing rewrite annotations for Ingress rule %v/%v: %v", ing.GetNamespace(), ing.GetName(), err)
|
||||||
}
|
}
|
||||||
loc.Redirect = *locRew
|
loc.Redirect = *locRew
|
||||||
|
loc.RateLimit = *rl
|
||||||
|
|
||||||
addLoc = false
|
addLoc = false
|
||||||
continue
|
continue
|
||||||
|
@ -635,9 +643,10 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg nginx.NginxConfigur
|
||||||
}
|
}
|
||||||
|
|
||||||
server.Locations = append(server.Locations, &nginx.Location{
|
server.Locations = append(server.Locations, &nginx.Location{
|
||||||
Path: nginxPath,
|
Path: nginxPath,
|
||||||
Upstream: *ups,
|
Upstream: *ups,
|
||||||
Redirect: *locRew,
|
Redirect: *locRew,
|
||||||
|
RateLimit: *rl,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,7 +186,10 @@ http {
|
||||||
{{- range $location := $server.Locations }}
|
{{- range $location := $server.Locations }}
|
||||||
{{- $path := buildLocation $location }}
|
{{- $path := buildLocation $location }}
|
||||||
location {{ $path }} {
|
location {{ $path }} {
|
||||||
location {{ $path }} {
|
{{/* if the location contains a rate limit annotation, create one */}}
|
||||||
|
{{ $limits := buildRateLimit $location }}
|
||||||
|
{{- range $limit := $limits }}
|
||||||
|
{{ $limit }}{{ end }}
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
|
|
||||||
# Pass Real IP
|
# Pass Real IP
|
||||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package nginx
|
package nginx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"k8s.io/contrib/ingress/controllers/nginx/nginx/ratelimit"
|
||||||
"k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite"
|
"k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -93,6 +94,7 @@ type Location struct {
|
||||||
IsDefBackend bool
|
IsDefBackend bool
|
||||||
Upstream Upstream
|
Upstream Upstream
|
||||||
Redirect rewrite.Redirect
|
Redirect rewrite.Redirect
|
||||||
|
RateLimit ratelimit.RateLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocationByPath sorts location by path
|
// LocationByPath sorts location by path
|
||||||
|
|
|
@ -25,8 +25,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
limitIp = "ingress-nginx.kubernetes.io/limit-connections"
|
limitIp = "ingress.kubernetes.io/limit-connections"
|
||||||
limitRps = "ingress-nginx.kubernetes.io/limit-rps"
|
limitRps = "ingress.kubernetes.io/limit-rps"
|
||||||
|
|
||||||
// allow 5 times the specified limit as burst
|
// allow 5 times the specified limit as burst
|
||||||
defBurst = 5
|
defBurst = 5
|
||||||
|
@ -39,18 +39,12 @@ const (
|
||||||
var (
|
var (
|
||||||
// ErrInvalidRateLimit is returned when the annotation caontains invalid values
|
// ErrInvalidRateLimit is returned when the annotation caontains invalid values
|
||||||
ErrInvalidRateLimit = errors.New("invalid rate limit value. Must be > 0")
|
ErrInvalidRateLimit = errors.New("invalid rate limit value. Must be > 0")
|
||||||
|
|
||||||
|
// ErrMissingAnnotations is returned when the ingress rule
|
||||||
|
// does not contains annotations related with rate limit
|
||||||
|
ErrMissingAnnotations = errors.New("no annotations present")
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrMissingAnnotations is returned when the ingress rule
|
|
||||||
// does not contains annotations related with rate limit
|
|
||||||
type ErrMissingAnnotations struct {
|
|
||||||
msg string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e ErrMissingAnnotations) Error() string {
|
|
||||||
return e.msg
|
|
||||||
}
|
|
||||||
|
|
||||||
// RateLimit returns rate limit configuration for an Ingress rule
|
// RateLimit returns rate limit configuration for an Ingress rule
|
||||||
// Is possible to limit the number of connections per IP address or
|
// Is possible to limit the number of connections per IP address or
|
||||||
// connections per second.
|
// connections per second.
|
||||||
|
@ -62,7 +56,8 @@ type RateLimit struct {
|
||||||
RPS Zone
|
RPS Zone
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zone returns information about the rate limit
|
// Zone returns information about the NGINX rate limit (limit_req_zone)
|
||||||
|
// http://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone
|
||||||
type Zone struct {
|
type Zone struct {
|
||||||
Name string
|
Name string
|
||||||
Limit int
|
Limit int
|
||||||
|
@ -81,7 +76,7 @@ func (a ingAnnotations) limitIp() int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a ingAnnotations) limitRps() int {
|
func (a ingAnnotations) limitRps() int {
|
||||||
|
@ -92,14 +87,14 @@ func (a ingAnnotations) limitRps() int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseAnnotations parses the annotations contained in the ingress
|
// ParseAnnotations parses the annotations contained in the ingress
|
||||||
// rule used to rewrite the defined paths
|
// rule used to rewrite the defined paths
|
||||||
func ParseAnnotations(ing *extensions.Ingress) (*RateLimit, error) {
|
func ParseAnnotations(ing *extensions.Ingress) (*RateLimit, error) {
|
||||||
if ing.GetAnnotations() == nil {
|
if ing.GetAnnotations() == nil {
|
||||||
return &RateLimit{}, ErrMissingAnnotations{"no annotations present"}
|
return &RateLimit{}, ErrMissingAnnotations
|
||||||
}
|
}
|
||||||
|
|
||||||
rps := ingAnnotations(ing.GetAnnotations()).limitRps()
|
rps := ingAnnotations(ing.GetAnnotations()).limitRps()
|
||||||
|
@ -107,8 +102,8 @@ func ParseAnnotations(ing *extensions.Ingress) (*RateLimit, error) {
|
||||||
|
|
||||||
if rps == 0 && conn == 0 {
|
if rps == 0 && conn == 0 {
|
||||||
return &RateLimit{
|
return &RateLimit{
|
||||||
Connections: Zone{"", -1, -1, 1},
|
Connections: Zone{},
|
||||||
RPS: Zone{"", -1, -1, 1},
|
RPS: Zone{},
|
||||||
}, ErrInvalidRateLimit
|
}, ErrInvalidRateLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,13 +63,13 @@ func TestAnnotations(t *testing.T) {
|
||||||
ing := buildIngress()
|
ing := buildIngress()
|
||||||
|
|
||||||
lip := ingAnnotations(ing.GetAnnotations()).limitIp()
|
lip := ingAnnotations(ing.GetAnnotations()).limitIp()
|
||||||
if lip != -1 {
|
if lip != 0 {
|
||||||
t.Error("Expected -1 in limit by ip but %v was returned", lip)
|
t.Error("Expected 0 in limit by ip but %v was returned", lip)
|
||||||
}
|
}
|
||||||
|
|
||||||
lrps := ingAnnotations(ing.GetAnnotations()).limitRps()
|
lrps := ingAnnotations(ing.GetAnnotations()).limitRps()
|
||||||
if lrps != -1 {
|
if lrps != 0 {
|
||||||
t.Error("Expected -1 in limit by rps but %v was returend", lrps)
|
t.Error("Expected 0 in limit by rps but %v was returend", lrps)
|
||||||
}
|
}
|
||||||
|
|
||||||
data := map[string]string{}
|
data := map[string]string{}
|
||||||
|
|
|
@ -45,8 +45,10 @@ var (
|
||||||
|
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
"buildLocation": buildLocation,
|
"buildLocation": buildLocation,
|
||||||
"buildProxyPass": buildProxyPass,
|
"buildProxyPass": buildProxyPass,
|
||||||
|
"buildRateLimitZones": buildRateLimitZones,
|
||||||
|
"buildRateLimit": buildRateLimit,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -180,3 +182,59 @@ func buildProxyPass(input interface{}) string {
|
||||||
// default proxy_pass
|
// default proxy_pass
|
||||||
return defProxyPass
|
return defProxyPass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buildRateLimitZones produces an array of limit_conn_zone in order to allow
|
||||||
|
// rate limiting of request. Each Ingress rule could have up to two zones, one
|
||||||
|
// for connection limit by IP address and other for limiting request per second
|
||||||
|
func buildRateLimitZones(input interface{}) []string {
|
||||||
|
zones := []string{}
|
||||||
|
|
||||||
|
servers, ok := input.([]*Server)
|
||||||
|
if !ok {
|
||||||
|
return zones
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, server := range servers {
|
||||||
|
for _, loc := range server.Locations {
|
||||||
|
|
||||||
|
if loc.RateLimit.Connections.Limit != -1 {
|
||||||
|
zone := fmt.Sprintf("limit_conn_zone $binary_remote_addr zone=%v:%v;",
|
||||||
|
loc.RateLimit.Connections.Name, loc.RateLimit.Connections.SharedSize)
|
||||||
|
zones = append(zones, zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
if loc.RateLimit.RPS.Limit != -1 {
|
||||||
|
zone := fmt.Sprintf("limit_conn_zone $binary_remote_addr zone=%v:%v rate=%vr/s;",
|
||||||
|
loc.RateLimit.Connections.Name, loc.RateLimit.Connections.SharedSize, loc.RateLimit.Connections.Limit)
|
||||||
|
zones = append(zones, zone)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return zones
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildRateLimit produces an array of limit_req to be used inside the Path of
|
||||||
|
// Ingress rules. The order: connections by IP first and RPS next.
|
||||||
|
func buildRateLimit(input interface{}) []string {
|
||||||
|
limits := []string{}
|
||||||
|
|
||||||
|
loc, ok := input.(*Location)
|
||||||
|
if !ok {
|
||||||
|
return limits
|
||||||
|
}
|
||||||
|
|
||||||
|
if loc.RateLimit.Connections.Limit != -1 {
|
||||||
|
limit := fmt.Sprintf("limit_conn %v %v;",
|
||||||
|
loc.RateLimit.Connections.Name, loc.RateLimit.Connections.Limit)
|
||||||
|
limits = append(limits, limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
if loc.RateLimit.RPS.Limit != -1 {
|
||||||
|
limit := fmt.Sprintf("limit_req zone=%v burst=%v nodelay;",
|
||||||
|
loc.RateLimit.Connections.Name, loc.RateLimit.Connections.Burst)
|
||||||
|
limits = append(limits, limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
return limits
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue