From 604544845c08d8ae51e6c49d343160f4679d98a3 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 | 4 ++ .../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(+), 5 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 1ee7bc9bf..ac39a2444 100644 --- a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl +++ b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl @@ -517,6 +517,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 }}; 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 105e919a0..6ab15058f 100644 --- a/core/pkg/ingress/controller/annotations.go +++ b/core/pkg/ingress/controller/annotations.go @@ -39,6 +39,7 @@ import ( "k8s.io/ingress/core/pkg/ingress/annotations/sslpassthrough" "k8s.io/ingress/core/pkg/ingress/errors" "k8s.io/ingress/core/pkg/ingress/resolver" + "k8s.io/ingress/core/pkg/ingress/annotations/proxybodysize" ) type extractorConfig interface { @@ -73,6 +74,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 a6b2d0b54..a88e9b7a6 100644 --- a/core/pkg/ingress/controller/controller.go +++ b/core/pkg/ingress/controller/controller.go @@ -663,6 +663,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 { @@ -679,6 +681,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) if loc.Redirect.FromToWWW { server.RedirectFromToWWW = true @@ -690,11 +693,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) if loc.Redirect.FromToWWW { diff --git a/core/pkg/ingress/types.go b/core/pkg/ingress/types.go index ba316532a..609f6191c 100644 --- a/core/pkg/ingress/types.go +++ b/core/pkg/ingress/types.go @@ -303,6 +303,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