Remove blank lines from template rendering

This commit is contained in:
Manuel de Brito Fontes 2016-05-30 13:39:10 -04:00
parent ccaf15cdd4
commit e603976721
6 changed files with 95 additions and 28 deletions

View file

@ -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,
}) })
} }
} }

View file

@ -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

View file

@ -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

View file

@ -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
} }

View file

@ -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{}

View file

@ -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
}