From 53bf1c58e5dc452860379df2af92b15b8cfe5189 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Date: Sun, 20 Aug 2017 02:00:01 -0500 Subject: [PATCH] Add annotation for client-body-buffer-size per location Adds an annotation which allows for client-body-buffer-size to be configured per specific locations specified in the ingress resource yaml. --- .../rootfs/etc/nginx/template/nginx.tmpl | 5 +- .../ingress/annotations/proxybodysize/main.go | 41 +++++++++++++ .../annotations/proxybodysize/main_test.go | 59 +++++++++++++++++++ core/pkg/ingress/controller/annotations.go | 2 + core/pkg/ingress/controller/controller.go | 14 +++-- core/pkg/ingress/types.go | 4 ++ 6 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 core/pkg/ingress/annotations/proxybodysize/main.go create mode 100644 core/pkg/ingress/annotations/proxybodysize/main_test.go diff --git a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl index 98147223e..af5610e2d 100644 --- a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl +++ b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl @@ -503,6 +503,10 @@ stream { {{ $path := buildLocation $location }} {{ $authPath := buildAuthLocation $location }} + {{ if $location.ProxyBodySize }} + client_body_buffer_size $location.ProxyBodySize + {{ end }} + {{ if not (empty $location.CertificateAuth.AuthSSLCert.CAFileName) }} # PEM sha: {{ $location.CertificateAuth.AuthSSLCert.PemSHA }} ssl_client_certificate {{ $location.CertificateAuth.AuthSSLCert.CAFileName }}; @@ -536,7 +540,6 @@ stream { client_max_body_size "{{ $location.Proxy.BodySize }}"; - set $target {{ $location.ExternalAuth.URL }}; proxy_pass $target; } diff --git a/core/pkg/ingress/annotations/proxybodysize/main.go b/core/pkg/ingress/annotations/proxybodysize/main.go new file mode 100644 index 000000000..0d5a799ca --- /dev/null +++ b/core/pkg/ingress/annotations/proxybodysize/main.go @@ -0,0 +1,41 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package proxybodysize + +import ( + extensions "k8s.io/api/extensions/v1beta1" + + "k8s.io/ingress/core/pkg/ingress/annotations/parser" +) + +const ( + annotation = "ingress.kubernetes.io/proxy-body-size" +) + +type proxyBodySize struct { +} + +// NewParser creates a new annotation parser +func NewParser() parser.IngressAnnotation { + return proxyBodySize{} +} + +// Parse parses the annotations contained in the ingress rule +// used to add an alias to the provided hosts +func (a proxyBodySize) Parse(ing *extensions.Ingress) (interface{}, error) { + return parser.GetStringAnnotation(annotation, ing) +} \ No newline at end of file diff --git a/core/pkg/ingress/annotations/proxybodysize/main_test.go b/core/pkg/ingress/annotations/proxybodysize/main_test.go new file mode 100644 index 000000000..9ea911813 --- /dev/null +++ b/core/pkg/ingress/annotations/proxybodysize/main_test.go @@ -0,0 +1,59 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package proxybodysize + +import ( + "testing" + + api "k8s.io/api/core/v1" + extensions "k8s.io/api/extensions/v1beta1" + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestParse(t *testing.T) { + ap := NewParser() + if ap == nil { + t.Fatalf("expected a parser.IngressAnnotation but returned nil") + } + + testCases := []struct { + annotations map[string]string + expected string + }{ + {map[string]string{annotation: "8k"}, "8k"}, + {map[string]string{annotation: "16k"}, "16k"}, + {map[string]string{annotation: ""}, ""}, + {map[string]string{}, ""}, + {nil, ""}, + } + + ing := &extensions.Ingress{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: "foo", + Namespace: api.NamespaceDefault, + }, + Spec: extensions.IngressSpec{}, + } + + for _, testCase := range testCases { + ing.SetAnnotations(testCase.annotations) + result, _ := ap.Parse(ing) + if result != testCase.expected { + t.Errorf("expected %v but returned %v, annotations: %s", testCase.expected, result, testCase.annotations) + } + } +} diff --git a/core/pkg/ingress/controller/annotations.go b/core/pkg/ingress/controller/annotations.go index 01f1cab8b..527914fde 100644 --- a/core/pkg/ingress/controller/annotations.go +++ b/core/pkg/ingress/controller/annotations.go @@ -38,6 +38,7 @@ import ( "k8s.io/ingress/core/pkg/ingress/errors" "k8s.io/ingress/core/pkg/ingress/resolver" "k8s.io/ingress/core/pkg/ingress/annotations/alias" + "k8s.io/ingress/core/pkg/ingress/annotations/proxybodysize" ) type extractorConfig interface { @@ -71,6 +72,7 @@ func newAnnotationExtractor(cfg extractorConfig) annotationExtractor { "SSLPassthrough": sslpassthrough.NewParser(), "ConfigurationSnippet": snippet.NewParser(), "Alias": alias.NewParser(), + "ProxyBodySize": proxybodysize.NewParser(), }, } } diff --git a/core/pkg/ingress/controller/controller.go b/core/pkg/ingress/controller/controller.go index bac29f23f..d46ded76b 100644 --- a/core/pkg/ingress/controller/controller.go +++ b/core/pkg/ingress/controller/controller.go @@ -661,6 +661,8 @@ func (ic *GenericController) getBackendServers() ([]*ingress.Backend, []*ingress nginxPath = path.Path } + proxyBodySize := anns["ProxyBodySize"].(string) + addLoc := true for _, loc := range server.Locations { if loc.Path == nginxPath { @@ -677,6 +679,7 @@ func (ic *GenericController) getBackendServers() ([]*ingress.Backend, []*ingress loc.Backend = ups.Name loc.Port = ups.Port loc.Service = ups.Service + loc.ProxyBodySize = proxyBodySize mergeLocationAnnotations(loc, anns) break } @@ -685,11 +688,12 @@ func (ic *GenericController) getBackendServers() ([]*ingress.Backend, []*ingress if addLoc { glog.V(3).Infof("adding location %v in ingress rule %v/%v upstream %v", nginxPath, ing.Namespace, ing.Name, ups.Name) loc := &ingress.Location{ - Path: nginxPath, - Backend: ups.Name, - IsDefBackend: false, - Service: ups.Service, - Port: ups.Port, + Path: nginxPath, + Backend: ups.Name, + IsDefBackend: false, + Service: ups.Service, + Port: ups.Port, + ProxyBodySize: proxyBodySize, } mergeLocationAnnotations(loc, anns) server.Locations = append(server.Locations, loc) diff --git a/core/pkg/ingress/types.go b/core/pkg/ingress/types.go index 00f5afa21..cac4fe1d6 100644 --- a/core/pkg/ingress/types.go +++ b/core/pkg/ingress/types.go @@ -297,6 +297,10 @@ type Location struct { // ConfigurationSnippet contains additional configuration for the backend // to be considered in the configuration of the location ConfigurationSnippet string `json:"configuration-snippet"` + // ProxyBodySize allows for the configuration of the client body + // buffer size for a specific location. + // +optional + ProxyBodySize string `json: "proxy-body-size,omitempty"` } // SSLPassthroughBackend describes a SSL upstream server configured