From b1e73f2e370afcc01f6165699bbea3d10e70cf7f Mon Sep 17 00:00:00 2001 From: decker Date: Thu, 14 Sep 2017 11:22:21 +0800 Subject: [PATCH] Surpport snippet for server section by the annotation of the ingess --- controllers/nginx/Makefile | 2 +- .../rootfs/etc/nginx/template/nginx.tmpl | 4 ++ .../ingress/annotations/serversnippet/main.go | 42 ++++++++++++++ .../annotations/serversnippet/main_test.go | 58 +++++++++++++++++++ core/pkg/ingress/controller/annotations.go | 11 ++++ core/pkg/ingress/controller/controller.go | 22 +++++++ core/pkg/ingress/types.go | 3 + 7 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 core/pkg/ingress/annotations/serversnippet/main.go create mode 100644 core/pkg/ingress/annotations/serversnippet/main_test.go diff --git a/controllers/nginx/Makefile b/controllers/nginx/Makefile index b1ff792ef..3dc7d9a50 100644 --- a/controllers/nginx/Makefile +++ b/controllers/nginx/Makefile @@ -3,7 +3,7 @@ all: push BUILDTAGS= # Use the 0.0 tag for testing, it shouldn't clobber any release builds -RELEASE?=0.9.0-beta.8 +RELEASE?=0.9.0-beta.8.hack PREFIX?=gcr.io/google_containers/nginx-ingress-controller GOOS?=linux DOCKER?=gcloud docker -- diff --git a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl index f3aebc447..c971fc0bf 100644 --- a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl +++ b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl @@ -286,6 +286,10 @@ http { {{ if $cfg.EnableVtsStatus }}vhost_traffic_status_filter_by_set_key $geoip_country_code country::$server_name;{{ end }} + {{ if not (empty $server.ServerSnippet) }} + {{ $server.ServerSnippet }} + {{ end }} + {{ range $location := $server.Locations }} {{ $path := buildLocation $location }} {{ $authPath := buildAuthLocation $location }} diff --git a/core/pkg/ingress/annotations/serversnippet/main.go b/core/pkg/ingress/annotations/serversnippet/main.go new file mode 100644 index 000000000..cdbce46fe --- /dev/null +++ b/core/pkg/ingress/annotations/serversnippet/main.go @@ -0,0 +1,42 @@ +/* +Copyright 2016 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 serversnippet + +import ( + extensions "k8s.io/client-go/pkg/apis/extensions/v1beta1" + + "k8s.io/ingress/core/pkg/ingress/annotations/parser" +) + +const ( + annotation = "ingress.kubernetes.io/server-snippet" +) + +type serverSnippet struct { +} + +// NewParser creates a new CORS annotation parser +func NewParser() parser.IngressAnnotation { + return serverSnippet{} +} + +// Parse parses the annotations contained in the ingress rule +// used to indicate if the location/s contains a fragment of +// configuration to be included inside the paths of the rules +func (a serverSnippet) Parse(ing *extensions.Ingress) (interface{}, error) { + return parser.GetStringAnnotation(annotation, ing) +} diff --git a/core/pkg/ingress/annotations/serversnippet/main_test.go b/core/pkg/ingress/annotations/serversnippet/main_test.go new file mode 100644 index 000000000..89113cbc5 --- /dev/null +++ b/core/pkg/ingress/annotations/serversnippet/main_test.go @@ -0,0 +1,58 @@ +/* +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 serversnippet + +import ( + "testing" + + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + api "k8s.io/client-go/pkg/api/v1" + extensions "k8s.io/client-go/pkg/apis/extensions/v1beta1" +) + +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: "more_headers"}, "more_headers"}, + {map[string]string{annotation: "false"}, "false"}, + {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 47f0a9acf..2e1c0fc52 100644 --- a/core/pkg/ingress/controller/annotations.go +++ b/core/pkg/ingress/controller/annotations.go @@ -31,6 +31,7 @@ import ( "k8s.io/ingress/core/pkg/ingress/annotations/ratelimit" "k8s.io/ingress/core/pkg/ingress/annotations/rewrite" "k8s.io/ingress/core/pkg/ingress/annotations/secureupstream" + "k8s.io/ingress/core/pkg/ingress/annotations/serversnippet" "k8s.io/ingress/core/pkg/ingress/annotations/sessionaffinity" "k8s.io/ingress/core/pkg/ingress/annotations/snippet" "k8s.io/ingress/core/pkg/ingress/annotations/sslpassthrough" @@ -67,6 +68,7 @@ func newAnnotationExtractor(cfg extractorConfig) annotationExtractor { "SessionAffinity": sessionaffinity.NewParser(), "SSLPassthrough": sslpassthrough.NewParser(), "ConfigurationSnippet": snippet.NewParser(), + "ServerSnippet": serversnippet.NewParser(), }, } } @@ -104,6 +106,7 @@ const ( healthCheck = "HealthCheck" sslPassthrough = "SSLPassthrough" sessionAffinity = "SessionAffinity" + serverSnippet = "ServerSnippet" ) func (e *annotationExtractor) SecureUpstream(ing *extensions.Ingress) *secureupstream.Secure { @@ -129,3 +132,11 @@ func (e *annotationExtractor) SessionAffinity(ing *extensions.Ingress) *sessiona val, _ := e.annotations[sessionAffinity].Parse(ing) return val.(*sessionaffinity.AffinityConfig) } + +func (e *annotationExtractor) ServerSnippet(ing *extensions.Ingress) string { + val, err := e.annotations[serverSnippet].Parse(ing) + if err != nil { + glog.Errorf("error parsing server snippet: %v", err) + } + return val.(string) +} diff --git a/core/pkg/ingress/controller/controller.go b/core/pkg/ingress/controller/controller.go index 7f2b8a36b..ac554f1cd 100644 --- a/core/pkg/ingress/controller/controller.go +++ b/core/pkg/ingress/controller/controller.go @@ -1028,6 +1028,28 @@ func (ic *GenericController) createServers(data []interface{}, } } + // configure server snippet + for _, ingIf := range data { + ing := ingIf.(*extensions.Ingress) + if !class.IsValid(ing, ic.cfg.IngressClass, ic.cfg.DefaultIngressClass) { + continue + } + + for _, rule := range ing.Spec.Rules { + host := rule.Host + if host == "" { + host = defServerName + } + + srvsnippet := ic.annotations.ServerSnippet(ing) + // only add a server snippet if the server does not have one previously configured + + if servers[host].ServerSnippet == "" && srvsnippet != "" { + servers[host].ServerSnippet = srvsnippet + } + } + } + return servers } diff --git a/core/pkg/ingress/types.go b/core/pkg/ingress/types.go index 10aa86416..0edb0907a 100644 --- a/core/pkg/ingress/types.go +++ b/core/pkg/ingress/types.go @@ -211,6 +211,9 @@ type Server struct { // used to determine if the secret changed without the use of file // system notifications SSLPemChecksum string `json:"sslPemChecksum"` + + // ServerSnippet returns the snippet of server + ServerSnippet string `json:"serverSnippet"` // Locations list of URIs configured in the server. Locations []*Location `json:"locations,omitempty"` }