From 1cc0a9596675df94152c7636a9a29db3d7fc476c Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Fri, 10 Mar 2017 12:34:13 -0300 Subject: [PATCH 01/35] Manually sync secrets from certificate authentication annotations --- core/pkg/ingress/controller/annotations.go | 22 ++++++++++++++++- core/pkg/ingress/controller/backend_ssl.go | 28 +++++++++++++++------- core/pkg/ingress/controller/controller.go | 17 +++++++++++-- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/core/pkg/ingress/controller/annotations.go b/core/pkg/ingress/controller/annotations.go index c0727dd87..5a8beeadf 100644 --- a/core/pkg/ingress/controller/annotations.go +++ b/core/pkg/ingress/controller/annotations.go @@ -17,8 +17,11 @@ limitations under the License. package controller import ( + "fmt" + "github.com/golang/glog" + "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/ingress/core/pkg/ingress/annotations/auth" @@ -47,11 +50,13 @@ type extractorConfig interface { } type annotationExtractor struct { - annotations map[string]parser.IngressAnnotation + secretResolver resolver.Secret + annotations map[string]parser.IngressAnnotation } func newAnnotationExtractor(cfg extractorConfig) annotationExtractor { return annotationExtractor{ + cfg, map[string]parser.IngressAnnotation{ "BasicDigestAuth": auth.NewParser(auth.AuthDirectory, cfg), "ExternalAuth": authreq.NewParser(), @@ -104,6 +109,7 @@ const ( healthCheck = "HealthCheck" sslPassthrough = "SSLPassthrough" sessionAffinity = "SessionAffinity" + certificateAuth = "CertificateAuth" ) func (e *annotationExtractor) SecureUpstream(ing *extensions.Ingress) bool { @@ -125,3 +131,17 @@ func (e *annotationExtractor) SessionAffinity(ing *extensions.Ingress) *sessiona val, _ := e.annotations[sessionAffinity].Parse(ing) return val.(*sessionaffinity.AffinityConfig) } + +func (e *annotationExtractor) ContainsCertificateAuth(ing *extensions.Ingress) bool { + val, _ := parser.GetStringAnnotation("ingress.kubernetes.io/auth-tls-secret", ing) + return val != "" +} + +func (e *annotationExtractor) CertificateAuthSecret(ing *extensions.Ingress) (*api.Secret, error) { + val, _ := parser.GetStringAnnotation("ingress.kubernetes.io/auth-tls-secret", ing) + if val == "" { + return nil, fmt.Errorf("ingress rule %v/%v does not contains the auth-tls-secret annotation", ing.Namespace, ing.Name) + } + + return e.secretResolver.GetSecret(val) +} diff --git a/core/pkg/ingress/controller/backend_ssl.go b/core/pkg/ingress/controller/backend_ssl.go index f67ff4743..7b7cbc7fd 100644 --- a/core/pkg/ingress/controller/backend_ssl.go +++ b/core/pkg/ingress/controller/backend_ssl.go @@ -18,6 +18,7 @@ package controller import ( "fmt" + "reflect" "strings" "time" @@ -68,13 +69,18 @@ func (ic *GenericController) syncSecret(k interface{}) error { } // create certificates and add or update the item in the store - _, exists = ic.sslCertTracker.Get(key) + cur, exists := ic.sslCertTracker.Get(key) if exists { - glog.V(3).Infof("updating secret %v/%v in the store ", sec.Namespace, sec.Name) + s := cur.(*ingress.SSLCert) + if reflect.DeepEqual(s, cert) { + // no need to update + return nil + } + glog.V(3).Infof("updating secret %v/%v in the store", sec.Namespace, sec.Name) ic.sslCertTracker.Update(key, cert) return nil } - glog.V(3).Infof("adding secret %v/%v to the store ", sec.Namespace, sec.Name) + glog.V(3).Infof("adding secret %v/%v to the store", sec.Namespace, sec.Name) ic.sslCertTracker.Add(key, cert) return nil } @@ -100,13 +106,13 @@ func (ic *GenericController) getPemCertificate(secretName string) (*ingress.SSLC var s *ingress.SSLCert if okcert && okkey { - glog.V(3).Infof("Found certificate and private key, configuring %v as a TLS Secret", secretName) + glog.V(3).Infof("found certificate and private key, configuring %v as a TLS Secret", secretName) s, err = ssl.AddOrUpdateCertAndKey(nsSecName, cert, key, ca) } else if ca != nil { - glog.V(3).Infof("Found only ca.crt, configuring %v as an Certificate Authentication secret", secretName) + glog.V(3).Infof("found only ca.crt, configuring %v as an Certificate Authentication secret", secretName) s, err = ssl.AddCertAuth(nsSecName, ca) } else { - return nil, fmt.Errorf("No keypair or CA cert could be found in %v", secretName) + return nil, fmt.Errorf("ko keypair or CA cert could be found in %v", secretName) } if err != nil { @@ -122,10 +128,14 @@ func (ic *GenericController) getPemCertificate(secretName string) (*ingress.SSLC func (ic *GenericController) secrReferenced(name, namespace string) bool { for _, ingIf := range ic.ingLister.Store.List() { ing := ingIf.(*extensions.Ingress) - str, err := parser.GetStringAnnotation("ingress.kubernetes.io/auth-tls-secret", ing) - if err == nil && str == fmt.Sprintf("%v/%v", namespace, name) { - return true + + if ic.annotations.ContainsCertificateAuth(ing) { + str, _ := parser.GetStringAnnotation("ingress.kubernetes.io/auth-tls-secret", ing) + if str == fmt.Sprintf("%v/%v", namespace, name) { + return true + } } + if ing.Namespace != namespace { continue } diff --git a/core/pkg/ingress/controller/controller.go b/core/pkg/ingress/controller/controller.go index b1c2607c7..2a9c692b3 100644 --- a/core/pkg/ingress/controller/controller.go +++ b/core/pkg/ingress/controller/controller.go @@ -170,6 +170,12 @@ func newIngressController(config *Configuration) *GenericController { } ic.recorder.Eventf(addIng, api.EventTypeNormal, "CREATE", fmt.Sprintf("Ingress %s/%s", addIng.Namespace, addIng.Name)) ic.syncQueue.Enqueue(obj) + if ic.annotations.ContainsCertificateAuth(addIng) { + s, err := ic.annotations.CertificateAuthSecret(addIng) + if err == nil { + ic.syncSecret(fmt.Sprintf("%v/%v", s.Namespace, s.Name)) + } + } }, DeleteFunc: func(obj interface{}) { delIng := obj.(*extensions.Ingress) @@ -209,6 +215,13 @@ func newIngressController(config *Configuration) *GenericController { }() } } + if ic.annotations.ContainsCertificateAuth(upIng) { + s, err := ic.annotations.CertificateAuthSecret(upIng) + if err == nil { + ic.syncSecret(fmt.Sprintf("%v/%v", s.Namespace, s.Name)) + } + } + ic.syncQueue.Enqueue(cur) } }, @@ -280,11 +293,11 @@ func newIngressController(config *Configuration) *GenericController { &api.Endpoints{}, ic.cfg.ResyncPeriod, eventHandler) ic.secrLister.Store, ic.secrController = cache.NewInformer( - cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "secrets", ic.cfg.Namespace, fields.Everything()), + cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "secrets", api.NamespaceAll, fields.Everything()), &api.Secret{}, ic.cfg.ResyncPeriod, secrEventHandler) ic.mapLister.Store, ic.mapController = cache.NewInformer( - cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "configmaps", ic.cfg.Namespace, fields.Everything()), + cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "configmaps", api.NamespaceAll, fields.Everything()), &api.ConfigMap{}, ic.cfg.ResyncPeriod, mapEventHandler) ic.svcLister.Indexer, ic.svcController = cache.NewIndexerInformer( From 04af55af3c6fd104caa36cad084a421b2b4bee94 Mon Sep 17 00:00:00 2001 From: Ricardo Pchevuzinske Katz Date: Sun, 12 Mar 2017 19:06:10 -0300 Subject: [PATCH 02/35] Adds support for root context redirection --- controllers/nginx/configuration.md | 3 +++ .../nginx/rootfs/etc/nginx/template/nginx.tmpl | 6 +++++- core/pkg/ingress/annotations/rewrite/main.go | 6 +++++- .../ingress/annotations/rewrite/main_test.go | 17 +++++++++++++++++ core/pkg/ingress/defaults/main.go | 2 ++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/controllers/nginx/configuration.md b/controllers/nginx/configuration.md index e8ffd81ff..b637f196e 100644 --- a/controllers/nginx/configuration.md +++ b/controllers/nginx/configuration.md @@ -40,6 +40,7 @@ The following annotations are supported: |Name |type| |---------------------------|------| |[ingress.kubernetes.io/add-base-url](#rewrite)|true or false| +|[ingress.kubernetes.io/app-root](#rewrite)|string| |[ingress.kubernetes.io/affinity](#session-affinity)|true or false| |[ingress.kubernetes.io/auth-realm](#authentication)|string| |[ingress.kubernetes.io/auth-secret](#authentication)|string| @@ -174,6 +175,8 @@ Set the annotation `ingress.kubernetes.io/rewrite-target` to the path expected b If the application contains relative links it is possible to add an additional annotation `ingress.kubernetes.io/add-base-url` that will prepend a [`base` tag](https://developer.mozilla.org/en/docs/Web/HTML/Element/base) in the header of the returned HTML from the backend. +If the Application Root is exposed in a different path and needs to be redirected, the annotation `ingress.kubernetes.io/app-root` might be used. + Please check the [rewrite](examples/rewrite/README.md) example. diff --git a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl index 9813bcd24..652ddcd4e 100644 --- a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl +++ b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl @@ -236,7 +236,11 @@ http { ssl_verify_client on; ssl_verify_depth {{ $location.CertificateAuth.ValidationDepth }}; {{ end }} - + {{ if not (empty $location.Redirect.AppRoot)}} + location = / { + return 302 ${{ location.Redirect.AppRoot }}; + } + {{ end }} {{ if not (empty $authPath) }} location = {{ $authPath }} { internal; diff --git a/core/pkg/ingress/annotations/rewrite/main.go b/core/pkg/ingress/annotations/rewrite/main.go index 999ef7844..c48573a74 100644 --- a/core/pkg/ingress/annotations/rewrite/main.go +++ b/core/pkg/ingress/annotations/rewrite/main.go @@ -28,6 +28,7 @@ const ( addBaseURL = "ingress.kubernetes.io/add-base-url" sslRedirect = "ingress.kubernetes.io/ssl-redirect" forceSSLRedirect = "ingress.kubernetes.io/force-ssl-redirect" + appRoot = "ingress.kubernetes.io/app-root" ) // Redirect describes the per location redirect config @@ -40,7 +41,8 @@ type Redirect struct { // SSLRedirect indicates if the location section is accessible SSL only SSLRedirect bool `json:"sslRedirect"` // ForceSSLRedirect indicates if the location section is accessible SSL only - ForceSSLRedirect bool `json:"forceSSLRedirect"` + ForceSSLRedirect bool `json:"forceSSLRedirect"` + AppRoot string `json:"appRoot"` } type rewrite struct { @@ -65,10 +67,12 @@ func (a rewrite) Parse(ing *extensions.Ingress) (interface{}, error) { fSslRe = a.backendResolver.GetDefaultBackend().ForceSSLRedirect } abu, _ := parser.GetBoolAnnotation(addBaseURL, ing) + ar, _ := parser.GetStringAnnotation(appRoot, ing) return &Redirect{ Target: rt, AddBaseURL: abu, SSLRedirect: sslRe, ForceSSLRedirect: fSslRe, + AppRoot: ar, }, nil } diff --git a/core/pkg/ingress/annotations/rewrite/main_test.go b/core/pkg/ingress/annotations/rewrite/main_test.go index 75daf01bc..2a3252184 100644 --- a/core/pkg/ingress/annotations/rewrite/main_test.go +++ b/core/pkg/ingress/annotations/rewrite/main_test.go @@ -158,3 +158,20 @@ func TestForceSSLRedirect(t *testing.T) { t.Errorf("Expected true but returned false") } } +func TestAppRoot(t *testing.T) { + ing := buildIngress() + + data := map[string]string{} + data[appRoot] = "/app1" + ing.SetAnnotations(data) + + i, _ := NewParser(mockBackend{true}).Parse(ing) + redirect, ok := i.(*Redirect) + if !ok { + t.Errorf("expected a App Context") + } + if redirect.AppRoot != "/app1" { + t.Errorf("Unexpected value got in AppRoot") + } + +} diff --git a/core/pkg/ingress/defaults/main.go b/core/pkg/ingress/defaults/main.go index d8420da04..92f5a72a2 100644 --- a/core/pkg/ingress/defaults/main.go +++ b/core/pkg/ingress/defaults/main.go @@ -6,6 +6,8 @@ import "net" // The reason of this requirements is the annotations are generic. If some implementation do not supports // one or more annotations it just can provides defaults type Backend struct { + // AppRoot contains the AppRoot for apps that doesn't exposes its content in the 'root' context + AppRoot string `json:"app-root"` // enables which HTTP codes should be passed for processing with the error_page directive // http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors From 0e5d3ca9e9cb1fb7ab9b87a52c4122ec63e941a4 Mon Sep 17 00:00:00 2001 From: Ricardo Pchevuzinske Katz Date: Mon, 13 Mar 2017 12:03:47 -0300 Subject: [PATCH 03/35] Adds support for root redirection, and improves rewrite documentation --- controllers/nginx/configuration.md | 2 +- .../rootfs/etc/nginx/template/nginx.tmpl | 19 +++--- core/pkg/ingress/annotations/rewrite/main.go | 5 +- examples/rewrite/README.md | 61 +++++++++++++++++++ 4 files changed, 76 insertions(+), 11 deletions(-) diff --git a/controllers/nginx/configuration.md b/controllers/nginx/configuration.md index b637f196e..f27bde70a 100644 --- a/controllers/nginx/configuration.md +++ b/controllers/nginx/configuration.md @@ -177,7 +177,7 @@ If the application contains relative links it is possible to add an additional a If the Application Root is exposed in a different path and needs to be redirected, the annotation `ingress.kubernetes.io/app-root` might be used. -Please check the [rewrite](examples/rewrite/README.md) example. +Please check the [rewrite](/examples/rewrite/README.md) example. ### Rate limiting diff --git a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl index e1df8e137..0e9c1bad1 100644 --- a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl +++ b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl @@ -236,9 +236,17 @@ http { ssl_verify_client on; ssl_verify_depth {{ $location.CertificateAuth.ValidationDepth }}; {{ end }} + + {{ if (or $location.Redirect.ForceSSLRedirect (and (not (empty $server.SSLCertificate)) $location.Redirect.SSLRedirect)) }} + # enforce ssl on server side + if ($pass_access_scheme = http) { + return 301 https://$host$request_uri; + } + {{ end }} + {{ if not (empty $location.Redirect.AppRoot)}} - location = / { - return 302 ${{ location.Redirect.AppRoot }}; + if ($uri = /) { + return 302 {{ $location.Redirect.AppRoot }}; } {{ end }} {{ if not (empty $authPath) }} @@ -283,12 +291,7 @@ http { error_page 401 = {{ $location.ExternalAuth.SigninURL }}; {{ end }} - {{ if (or $location.Redirect.ForceSSLRedirect (and (not (empty $server.SSLCertificate)) $location.Redirect.SSLRedirect)) }} - # enforce ssl on server side - if ($pass_access_scheme = http) { - return 301 https://$host$request_uri; - } - {{ end }} + {{/* if the location contains a rate limit annotation, create one */}} {{ $limits := buildRateLimit $location }} {{ range $limit := $limits }} diff --git a/core/pkg/ingress/annotations/rewrite/main.go b/core/pkg/ingress/annotations/rewrite/main.go index c48573a74..e522a275a 100644 --- a/core/pkg/ingress/annotations/rewrite/main.go +++ b/core/pkg/ingress/annotations/rewrite/main.go @@ -41,8 +41,9 @@ type Redirect struct { // SSLRedirect indicates if the location section is accessible SSL only SSLRedirect bool `json:"sslRedirect"` // ForceSSLRedirect indicates if the location section is accessible SSL only - ForceSSLRedirect bool `json:"forceSSLRedirect"` - AppRoot string `json:"appRoot"` + ForceSSLRedirect bool `json:"forceSSLRedirect"` + // AppRoot defines the Application Root that the Controller must redirect if it's not in '/' context + AppRoot string `json:"appRoot"` } type rewrite struct { diff --git a/examples/rewrite/README.md b/examples/rewrite/README.md index a878d52ea..66d7bb038 100644 --- a/examples/rewrite/README.md +++ b/examples/rewrite/README.md @@ -1,3 +1,28 @@ +# Sticky Session + +This example demonstrates how to use the Rewrite annotations + +## Prerequisites + +You will need to make sure you Ingress targets exactly one Ingress +controller by specifying the [ingress.class annotation](/examples/PREREQUISITES.md#ingress-class), +and that you have an ingress controller [running](/examples/deployment) in your cluster. + +## Deployment + +Rewriting can be controlled using the following annotations: + +|Name|Description|Values| +| --- | --- | --- | +|ingress.kubernetes.io/rewrite-target|Target URI where the traffic must be redirected|string| +|ingress.kubernetes.io/add-base-url|indicates if is required to add a base tag in the head of the responses from the upstream servers|bool| +|ingress.kubernetes.io/ssl-redirect|Indicates if the location section is accessible SSL only (defaults to True when Ingress contains a Certificate)|bool| +|ingress.kubernetes.io/force-ssl-redirect|Forces the redirection to HTTPS even if the Ingress is not TLS Enabled|bool| +|ingress.kubernetes.io/app-root|Defines the Application Root that the Controller must redirect if it's not in '/' context|string| + +## Validation + +### Rewrite Target Create an Ingress rule with a rewrite annotation: ``` $ echo " @@ -64,3 +89,39 @@ BODY: -no body in request- ``` +### App Root + +Create an Ingress rule with a app-root annotation: +``` +$ echo " +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + annotations: + ingress.kubernetes.io/app-root: /app1 + name: approot + namespace: default +spec: + rules: + - host: approot.bar.com + http: + paths: + - backend: + serviceName: echoheaders + servicePort: 80 + path: / +" | kubectl create -f - +``` + +Check the rewrite is working + +``` +$ curl -I -k http://approot.bar.com/ +HTTP/1.1 302 Moved Temporarily +Server: nginx/1.11.10 +Date: Mon, 13 Mar 2017 14:57:15 GMT +Content-Type: text/html +Content-Length: 162 +Location: http://stickyingress.example.com/app1 +Connection: keep-alive +``` \ No newline at end of file From bbeb9a766cdae4bc97cd3bfd39d0ccd490fe4840 Mon Sep 17 00:00:00 2001 From: ohmystack Date: Mon, 13 Mar 2017 19:15:09 +0800 Subject: [PATCH 04/35] Fix add-base-url The "base" tag is used for completing a relative link in current page by browser, so it should stay the same with the base url of current page. --- controllers/nginx/pkg/template/template.go | 19 +++++++----- .../nginx/pkg/template/template_test.go | 30 ++++++++++++------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/controllers/nginx/pkg/template/template.go b/controllers/nginx/pkg/template/template.go index 8262a5873..578dd6274 100644 --- a/controllers/nginx/pkg/template/template.go +++ b/controllers/nginx/pkg/template/template.go @@ -205,7 +205,13 @@ func buildLocation(input interface{}) string { if path == "/" { return fmt.Sprintf("~* %s", path) } - return fmt.Sprintf("~* ^%s", path) + // baseuri regex will parse basename from the given location + baseuri := `(?.*)` + if !strings.HasSuffix(path, slash) { + // Not treat the slash after "location path" as a part of baseuri + baseuri = fmt.Sprintf(`\/?%s`, baseuri) + } + return fmt.Sprintf(`~* ^%s%s`, path, baseuri) } return path @@ -273,13 +279,10 @@ func buildProxyPass(b interface{}, loc interface{}) string { if len(location.Redirect.Target) > 0 { abu := "" if location.Redirect.AddBaseURL { - bPath := location.Redirect.Target - if !strings.HasSuffix(bPath, slash) { - bPath = fmt.Sprintf("%s/", bPath) - } - - abu = fmt.Sprintf(`subs_filter '' '' r; - subs_filter '' '' r; + // path has a slash suffix, so that it can be connected with baseuri directly + bPath := fmt.Sprintf("%s%s", path, "$baseuri") + abu = fmt.Sprintf(`subs_filter '' '' r; + subs_filter '' '' r; `, bPath, bPath) } diff --git a/controllers/nginx/pkg/template/template_test.go b/controllers/nginx/pkg/template/template_test.go index 20e860c72..c6cbfbc14 100644 --- a/controllers/nginx/pkg/template/template_test.go +++ b/controllers/nginx/pkg/template/template_test.go @@ -45,33 +45,43 @@ var ( rewrite /(.*) /jenkins/$1 break; proxy_pass http://upstream-name; `, false}, - "redirect /something to /": {"/something", "/", "~* ^/something", ` + "redirect /something to /": {"/something", "/", `~* ^/something\/?(?.*)`, ` rewrite /something/(.*) /$1 break; rewrite /something / break; proxy_pass http://upstream-name; `, false}, - "redirect /something-complex to /not-root": {"/something-complex", "/not-root", "~* ^/something-complex", ` + "redirect /end-with-slash/ to /not-root": {"/end-with-slash/", "/not-root", "~* ^/end-with-slash/(?.*)", ` + rewrite /end-with-slash/(.*) /not-root/$1 break; + proxy_pass http://upstream-name; + `, false}, + "redirect /something-complex to /not-root": {"/something-complex", "/not-root", `~* ^/something-complex\/?(?.*)`, ` rewrite /something-complex/(.*) /not-root/$1 break; proxy_pass http://upstream-name; `, false}, "redirect / to /jenkins and rewrite": {"/", "/jenkins", "~* /", ` rewrite /(.*) /jenkins/$1 break; proxy_pass http://upstream-name; - subs_filter '' '' r; - subs_filter '' '' r; + subs_filter '' '' r; + subs_filter '' '' r; `, true}, - "redirect /something to / and rewrite": {"/something", "/", "~* ^/something", ` + "redirect /something to / and rewrite": {"/something", "/", `~* ^/something\/?(?.*)`, ` rewrite /something/(.*) /$1 break; rewrite /something / break; proxy_pass http://upstream-name; - subs_filter '' '' r; - subs_filter '' '' r; + subs_filter '' '' r; + subs_filter '' '' r; `, true}, - "redirect /something-complex to /not-root and rewrite": {"/something-complex", "/not-root", "~* ^/something-complex", ` + "redirect /end-with-slash/ to /not-root and rewrite": {"/end-with-slash/", "/not-root", `~* ^/end-with-slash/(?.*)`, ` + rewrite /end-with-slash/(.*) /not-root/$1 break; + proxy_pass http://upstream-name; + subs_filter '' '' r; + subs_filter '' '' r; + `, true}, + "redirect /something-complex to /not-root and rewrite": {"/something-complex", "/not-root", `~* ^/something-complex\/?(?.*)`, ` rewrite /something-complex/(.*) /not-root/$1 break; proxy_pass http://upstream-name; - subs_filter '' '' r; - subs_filter '' '' r; + subs_filter '' '' r; + subs_filter '' '' r; `, true}, } ) From 0fa2a32b6fd49a34473671048860cd59bf204656 Mon Sep 17 00:00:00 2001 From: Ian Quick Date: Mon, 13 Mar 2017 18:39:35 -0400 Subject: [PATCH 05/35] pass the ingress in or the 2nd invocation will be used --- core/pkg/ingress/status/status.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/pkg/ingress/status/status.go b/core/pkg/ingress/status/status.go index 0dc855513..6e54d422b 100644 --- a/core/pkg/ingress/status/status.go +++ b/core/pkg/ingress/status/status.go @@ -252,7 +252,7 @@ func (s *statusSync) updateStatus(newIPs []api.LoadBalancerIngress) { continue } - go func(wg *sync.WaitGroup) { + go func(wg *sync.WaitGroup, ing *extensions.Ingress) { defer wg.Done() ingClient := s.Client.Extensions().Ingresses(ing.Namespace) currIng, err := ingClient.Get(ing.Name) @@ -274,7 +274,7 @@ func (s *statusSync) updateStatus(newIPs []api.LoadBalancerIngress) { if err != nil { glog.Warningf("error updating ingress rule: %v", err) } - }(&wg) + }(&wg, ing) } wg.Wait() From c10c0fb196c3265ca54af1feb4bf108e0302a79f Mon Sep 17 00:00:00 2001 From: Lee Calcote Date: Mon, 13 Mar 2017 22:10:29 -0500 Subject: [PATCH 06/35] Update README.md Missing 'e' in achieve --- controllers/gce/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/gce/README.md b/controllers/gce/README.md index c68949150..1dbf3b0e4 100644 --- a/controllers/gce/README.md +++ b/controllers/gce/README.md @@ -18,7 +18,7 @@ __A reminder on Services__: A Kubernetes Service defines a set of pods and a mea ### L7 Load balancing on Kubernetes -To achive L7 loadbalancing through Kubernetes, we employ a resource called `Ingress`. The Ingress is consumed by this loadbalancer controller, which creates the following GCE resource graph: +To achieve L7 loadbalancing through Kubernetes, we employ a resource called `Ingress`. The Ingress is consumed by this loadbalancer controller, which creates the following GCE resource graph: [Global Forwarding Rule](https://cloud.google.com/compute/docs/load-balancing/http/global-forwarding-rules) -> [TargetHttpProxy](https://cloud.google.com/compute/docs/load-balancing/http/target-proxies) -> [Url Map](https://cloud.google.com/compute/docs/load-balancing/http/url-map) -> [Backend Service](https://cloud.google.com/compute/docs/load-balancing/http/backend-service) -> [Instance Group](https://cloud.google.com/compute/docs/instance-groups/) From b0d9d76aa71dec00b61aef531fd1b0ee25f63459 Mon Sep 17 00:00:00 2001 From: Lee Calcote Date: Mon, 13 Mar 2017 22:20:42 -0500 Subject: [PATCH 07/35] Update README.md Changed "Ingerss" to "Ingress" --- docs/faq/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq/README.md b/docs/faq/README.md index dd36de9a1..865921581 100644 --- a/docs/faq/README.md +++ b/docs/faq/README.md @@ -23,7 +23,7 @@ Table of Contents The Kubernetes Service is an abstraction over endpoints (pod-ip:port pairings). The Ingress is an abstraction over Services. This doesn't mean all Ingress controller must route *through* a Service, but rather, that routing, security -and auth configuration is represented in the Ingerss resource per Service, and +and auth configuration is represented in the Ingress resource per Service, and not per pod. As long as this configuration is respected, a given Ingress controller is free to route to the DNS name of a Service, the VIP, a NodePort, or directly to the Service's endpoints. From c6195c44f3c124e918173c3627ec8fc0d5b5b612 Mon Sep 17 00:00:00 2001 From: Giancarlo Rubio Date: Mon, 13 Mar 2017 21:50:27 +0100 Subject: [PATCH 08/35] Validate if configmap exist and is in the namespace/name format Verifiy if watch-namespace option exist --- core/pkg/ingress/controller/launch.go | 16 ++++++-- core/pkg/k8s/main.go | 24 +++++++++++ core/pkg/k8s/main_test.go | 58 +++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/core/pkg/ingress/controller/launch.go b/core/pkg/ingress/controller/launch.go index 0109d239f..78704960d 100644 --- a/core/pkg/ingress/controller/launch.go +++ b/core/pkg/ingress/controller/launch.go @@ -128,10 +128,20 @@ func NewIngressController(backend ingress.Controller) *GenericController { glog.Infof("service %v validated as source of Ingress status", *publishSvc) } - if *configMap != "" { - _, _, err = k8s.ParseNameNS(*configMap) + for _, configMap := range []string{*configMap, *tcpConfigMapName, *udpConfigMapName} { + _, err = k8s.IsValidConfigMap(kubeClient, configMap) + if err != nil { - glog.Fatalf("configmap error: %v", err) + glog.Fatalf("%v", err) + } + } + + if *watchNamespace != "" { + + _, err = k8s.IsValidNamespace(kubeClient, *watchNamespace) + + if err != nil { + glog.Fatalf("no watchNamespace with name %v found: %v", *watchNamespace, err) } } diff --git a/core/pkg/k8s/main.go b/core/pkg/k8s/main.go index 2f0caf5e5..af0b5df73 100644 --- a/core/pkg/k8s/main.go +++ b/core/pkg/k8s/main.go @@ -34,6 +34,30 @@ func IsValidService(kubeClient clientset.Interface, name string) (*api.Service, return kubeClient.Core().Services(ns).Get(name) } +// isValidConfigMap check if exists a configmap with the specified name +func IsValidConfigMap(kubeClient clientset.Interface, fullName string) (*api.ConfigMap, error) { + + ns, name, err := ParseNameNS(fullName) + + if err != nil { + return nil, err + } + + configMap, err := kubeClient.Core().ConfigMaps(ns).Get(name) + + if err != nil { + return nil, fmt.Errorf("configmap not found: %v", err) + } + + return configMap, nil + +} + +// isValidNamespace chck if exists a namespace with the specified name +func IsValidNamespace(kubeClient clientset.Interface, name string) (*api.Namespace, error) { + return kubeClient.Core().Namespaces().Get(name) +} + // IsValidSecret checks if exists a secret with the specified name func IsValidSecret(kubeClient clientset.Interface, name string) (*api.Secret, error) { ns, name, err := ParseNameNS(name) diff --git a/core/pkg/k8s/main_test.go b/core/pkg/k8s/main_test.go index 384a7313d..58f640dec 100644 --- a/core/pkg/k8s/main_test.go +++ b/core/pkg/k8s/main_test.go @@ -85,6 +85,64 @@ func TestIsValidService(t *testing.T) { } } +func TestIsValidNamespace(t *testing.T) { + + fk := testclient.NewSimpleClientset(&api.Namespace{ + ObjectMeta: api.ObjectMeta{ + Name: "default", + }, + }) + + _, err := IsValidNamespace(fk, "empty") + if err == nil { + t.Errorf("expected error but return nill") + } + + ns, err := IsValidNamespace(fk, "default") + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if ns == nil { + t.Errorf("expected a configmap but returned nil") + } + +} + +func TestIsValidConfigMap(t *testing.T) { + + fk := testclient.NewSimpleClientset(&api.ConfigMap{ + ObjectMeta: api.ObjectMeta{ + Namespace: api.NamespaceDefault, + Name: "demo", + }, + }) + + _, err := IsValidConfigMap(fk, "") + if err == nil { + t.Errorf("expected error but return nill") + } + + s, err := IsValidConfigMap(fk, "default/demo") + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if s == nil { + t.Errorf("expected a configmap but returned nil") + } + + fk = testclient.NewSimpleClientset() + s, err = IsValidConfigMap(fk, "default/demo") + if err == nil { + t.Errorf("expected an error but returned nil") + } + if s != nil { + t.Errorf("unexpected Configmap returned: %v", s) + } + +} + func TestIsValidSecret(t *testing.T) { fk := testclient.NewSimpleClientset(&api.Secret{ ObjectMeta: api.ObjectMeta{ From 3b152e6aa7a8c1153059e697a589ffde7d2db471 Mon Sep 17 00:00:00 2001 From: caiyixiang Date: Tue, 14 Mar 2017 19:19:21 +0800 Subject: [PATCH 09/35] 0 --- controllers/nginx/pkg/template/template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/nginx/pkg/template/template.go b/controllers/nginx/pkg/template/template.go index 8262a5873..234dd885b 100644 --- a/controllers/nginx/pkg/template/template.go +++ b/controllers/nginx/pkg/template/template.go @@ -202,7 +202,7 @@ func buildLocation(input interface{}) string { path := location.Path if len(location.Redirect.Target) > 0 && location.Redirect.Target != path { - if path == "/" { + if path == slash { return fmt.Sprintf("~* %s", path) } return fmt.Sprintf("~* ^%s", path) From 6e017269dba6902e7e3f959609dbe01791cc7b6c Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Tue, 14 Mar 2017 13:47:34 +0100 Subject: [PATCH 10/35] Fix grammar in error messages --- core/pkg/ingress/controller/backend_ssl.go | 2 +- core/pkg/ingress/controller/controller.go | 6 +++--- core/pkg/ingress/controller/named_port.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/pkg/ingress/controller/backend_ssl.go b/core/pkg/ingress/controller/backend_ssl.go index 7b7cbc7fd..1cac8e067 100644 --- a/core/pkg/ingress/controller/backend_ssl.go +++ b/core/pkg/ingress/controller/backend_ssl.go @@ -93,7 +93,7 @@ func (ic *GenericController) getPemCertificate(secretName string) (*ingress.SSLC return nil, fmt.Errorf("error retriveing secret %v: %v", secretName, err) } if !exists { - return nil, fmt.Errorf("secret named %v does not exists", secretName) + return nil, fmt.Errorf("secret named %v does not exist", secretName) } secret := secretInterface.(*api.Secret) diff --git a/core/pkg/ingress/controller/controller.go b/core/pkg/ingress/controller/controller.go index 2a9c692b3..bbb96df36 100644 --- a/core/pkg/ingress/controller/controller.go +++ b/core/pkg/ingress/controller/controller.go @@ -564,7 +564,7 @@ func (ic *GenericController) getDefaultUpstream() *ingress.Backend { } if !svcExists { - glog.Warningf("service %v does not exists", svcKey) + glog.Warningf("service %v does not exist", svcKey) upstream.Endpoints = append(upstream.Endpoints, newDefaultServer()) return upstream } @@ -706,7 +706,7 @@ func (ic GenericController) GetAuthCertificate(secretName string) (*resolver.Aut bc, exists := ic.sslCertTracker.Get(secretName) if !exists { - return &resolver.AuthSSLCert{}, fmt.Errorf("secret %v does not exists", secretName) + return &resolver.AuthSSLCert{}, fmt.Errorf("secret %v does not exist", secretName) } cert := bc.(*ingress.SSLCert) return &resolver.AuthSSLCert{ @@ -805,7 +805,7 @@ func (ic *GenericController) serviceEndpoints(svcKey, backendPort string, } if !svcExists { - err = fmt.Errorf("service %v does not exists", svcKey) + err = fmt.Errorf("service %v does not exist", svcKey) return upstreams, err } diff --git a/core/pkg/ingress/controller/named_port.go b/core/pkg/ingress/controller/named_port.go index c1cdeb6e2..abc1e6ef2 100644 --- a/core/pkg/ingress/controller/named_port.go +++ b/core/pkg/ingress/controller/named_port.go @@ -32,7 +32,7 @@ import ( ) // checkSvcForUpdate verifies if one of the running pods for a service contains -// named port. If the annotation in the service does not exists or is not equals +// named port. If the annotation in the service does not exist or is not equals // to the port mapping obtained from the pod the service must be updated to reflect // the current state func (ic *GenericController) checkSvcForUpdate(svc *api.Service) error { From dbeead3615d61344e594c4db74a9fc0a5a04c3c9 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Tue, 14 Mar 2017 13:48:20 +0100 Subject: [PATCH 11/35] Fix typo in error message --- core/pkg/ingress/controller/backend_ssl.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/pkg/ingress/controller/backend_ssl.go b/core/pkg/ingress/controller/backend_ssl.go index 1cac8e067..e75d8ff0e 100644 --- a/core/pkg/ingress/controller/backend_ssl.go +++ b/core/pkg/ingress/controller/backend_ssl.go @@ -90,7 +90,7 @@ func (ic *GenericController) syncSecret(k interface{}) error { func (ic *GenericController) getPemCertificate(secretName string) (*ingress.SSLCert, error) { secretInterface, exists, err := ic.secrLister.Store.GetByKey(secretName) if err != nil { - return nil, fmt.Errorf("error retriveing secret %v: %v", secretName, err) + return nil, fmt.Errorf("error retrieving secret %v: %v", secretName, err) } if !exists { return nil, fmt.Errorf("secret named %v does not exist", secretName) From 3dece0ab70511550d865e80115feac8f0efebbcf Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Tue, 7 Mar 2017 15:27:53 +0100 Subject: [PATCH 12/35] Avoid a nil-reference when the temporary file cannot be created --- core/pkg/net/ssl/ssl.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/pkg/net/ssl/ssl.go b/core/pkg/net/ssl/ssl.go index 2088c2a61..c758423fc 100644 --- a/core/pkg/net/ssl/ssl.go +++ b/core/pkg/net/ssl/ssl.go @@ -43,10 +43,10 @@ func AddOrUpdateCertAndKey(name string, cert, key, ca []byte) (*ingress.SSLCert, tempPemFile, err := ioutil.TempFile(ingress.DefaultSSLDirectory, pemName) - glog.V(3).Infof("Creating temp file %v for Keypair: %v", tempPemFile.Name(), pemName) if err != nil { return nil, fmt.Errorf("could not create temp pem file %v: %v", pemFileName, err) } + glog.V(3).Infof("Creating temp file %v for Keypair: %v", tempPemFile.Name(), pemName) _, err = tempPemFile.Write(cert) if err != nil { From 1e1e4dca9418354a935a2b8f0aeb3d9d0429271f Mon Sep 17 00:00:00 2001 From: Giancarlo Rubio Date: Tue, 14 Mar 2017 14:45:47 +0100 Subject: [PATCH 13/35] skip validation on empty configmap --- core/pkg/ingress/controller/launch.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/pkg/ingress/controller/launch.go b/core/pkg/ingress/controller/launch.go index 78704960d..144da3969 100644 --- a/core/pkg/ingress/controller/launch.go +++ b/core/pkg/ingress/controller/launch.go @@ -129,6 +129,11 @@ func NewIngressController(backend ingress.Controller) *GenericController { } for _, configMap := range []string{*configMap, *tcpConfigMapName, *udpConfigMapName} { + + if configMap == "" { + continue + } + _, err = k8s.IsValidConfigMap(kubeClient, configMap) if err != nil { From 1aa822388993a510b9cb679687c70c15917ed41b Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Mon, 13 Mar 2017 22:39:21 -0300 Subject: [PATCH 14/35] Release 0.9-beta.3 --- controllers/nginx/Changelog.md | 69 +++++++++++++++++++ controllers/nginx/Makefile | 2 +- docs/troubleshooting.md | 2 +- .../nginx/nginx-ingress-controller.yaml | 2 +- .../custom-errors/nginx/rc-custom-errors.yaml | 2 +- .../nginx/nginx-ingress-controller.yaml | 2 +- .../custom-template/custom-template.yaml | 2 +- .../nginx/nginx-ingress-daemonset.yaml | 2 +- .../kubeadm/nginx-ingress-controller.yaml | 2 +- .../nginx/nginx-ingress-controller.yaml | 2 +- .../nginx/nginx-ingress-deployment.yaml | 2 +- .../nginx/nginx-ingress-controller.yaml | 2 +- 12 files changed, 80 insertions(+), 11 deletions(-) diff --git a/controllers/nginx/Changelog.md b/controllers/nginx/Changelog.md index 761cda127..69eee1dff 100644 --- a/controllers/nginx/Changelog.md +++ b/controllers/nginx/Changelog.md @@ -1,5 +1,74 @@ Changelog +### 0.9-beta.3 + +**Image:** `gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3` + +*New Features:* + +- Custom log formats using `log-format-upstream` directive in the configuration configmap. +- Force redirect to SSL using the annotation `ingress.kubernetes.io/force-ssl-redirect` +- Prometheus metric for VTS status module (transparent, just enable vts stats) +- Improved external authentication adding `ingress.kubernetes.io/auth-signin` annotation. Please check this [example](https://github.com/kubernetes/ingress/tree/master/examples/external-auth/nginx) + + +*Breaking changes:* + +- `ssl-dh-param` configuration in configmap is now the name of a secret that contains the Diffie-Hellman key + +*Changes:* + +- [X] [#433](https://github.com/kubernetes/ingress/pull/433) close over the ingress variable or the last assignment will be used +- [X] [#424](https://github.com/kubernetes/ingress/pull/424) Manually sync secrets from certificate authentication annotations +- [X] [#423](https://github.com/kubernetes/ingress/pull/423) Scrap json metrics from nginx vts module when enabled +- [X] [#418](https://github.com/kubernetes/ingress/pull/418) Only update Ingress status for the configured class +- [X] [#415](https://github.com/kubernetes/ingress/pull/415) Improve external authentication docs +- [X] [#410](https://github.com/kubernetes/ingress/pull/410) Add support for "signin url" +- [X] [#409](https://github.com/kubernetes/ingress/pull/409) Allow custom http2 header sizes +- [X] [#408](https://github.com/kubernetes/ingress/pull/408) Review docs +- [X] [#406](https://github.com/kubernetes/ingress/pull/406) Add debug info and fix spelling +- [X] [#402](https://github.com/kubernetes/ingress/pull/402) allow specifying custom dh param +- [X] [#397](https://github.com/kubernetes/ingress/pull/397) Fix external auth +- [X] [#394](https://github.com/kubernetes/ingress/pull/394) Update README.md +- [X] [#392](https://github.com/kubernetes/ingress/pull/392) Fix http2 header size +- [X] [#391](https://github.com/kubernetes/ingress/pull/391) remove tmp nginx-diff files +- [X] [#390](https://github.com/kubernetes/ingress/pull/390) Fix RateLimit comment +- [X] [#385](https://github.com/kubernetes/ingress/pull/385) add Copyright +- [X] [#382](https://github.com/kubernetes/ingress/pull/382) Ingress Fake Certificate generation +- [X] [#380](https://github.com/kubernetes/ingress/pull/380) Fix custom log format +- [X] [#373](https://github.com/kubernetes/ingress/pull/373) Cleanup +- [X] [#371](https://github.com/kubernetes/ingress/pull/371) add configuration to disable listening on ipv6 +- [X] [#370](https://github.com/kubernetes/ingress/pull/270) Add documentation for ingress.kubernetes.io/force-ssl-redirect +- [X] [#369](https://github.com/kubernetes/ingress/pull/369) Minor text fix for "ApiServer" +- [X] [#367](https://github.com/kubernetes/ingress/pull/367) BuildLogFormatUpstream was always using the default log-format +- [X] [#366](https://github.com/kubernetes/ingress/pull/366) add_judgment +- [X] [#365](https://github.com/kubernetes/ingress/pull/365) add ForceSSLRedirect ingress annotation +- [X] [#364](https://github.com/kubernetes/ingress/pull/364) Fix error caused by increasing proxy_buffer_size (#363) +- [X] [#362](https://github.com/kubernetes/ingress/pull/362) Fix ingress class +- [X] [#360](https://github.com/kubernetes/ingress/pull/360) add example of 'run multiple nginx ingress controllers as a deployment' +- [X] [#358](https://github.com/kubernetes/ingress/pull/358) Checks if the TLS secret contains a valid keypair structure +- [X] [#356](https://github.com/kubernetes/ingress/pull/356) Disable listen only on ipv6 and fix proxy_protocol +- [X] [#354](https://github.com/kubernetes/ingress/pull/354) add judgment +- [X] [#352](https://github.com/kubernetes/ingress/pull/352) Add ability to customize upstream and stream log format +- [X] [#351](https://github.com/kubernetes/ingress/pull/351) Enable custom election id for status sync. +- [X] [#347](https://github.com/kubernetes/ingress/pull/347) Fix client source IP address +- [X] [#345](https://github.com/kubernetes/ingress/pull/345) Fix lint error +- [X] [#344](https://github.com/kubernetes/ingress/pull/344) Refactoring of TCP and UDP services +- [X] [#343](https://github.com/kubernetes/ingress/pull/343) Fix node lister when --watch-namespace is used +- [X] [#341](https://github.com/kubernetes/ingress/pull/341) Do not run coverage check in the default target. +- [X] [#340](https://github.com/kubernetes/ingress/pull/340) Add support for specify proxy cookie path/domain +- [X] [#337](https://github.com/kubernetes/ingress/pull/337) Fix for formatting error introduced in #304 +- [X] [#335](https://github.com/kubernetes/ingress/pull/335) Fix for vet complaints: +- [X] [#332](https://github.com/kubernetes/ingress/pull/332) Add annotation to customize nginx configuration +- [X] [#331](https://github.com/kubernetes/ingress/pull/331) Correct spelling mistake +- [X] [#328](https://github.com/kubernetes/ingress/pull/328) fix misspell "affinity" in main.go +- [X] [#326](https://github.com/kubernetes/ingress/pull/326) add nginx daemonset example +- [X] [#311](https://github.com/kubernetes/ingress/pull/311) Sort stream service ports to avoid extra reloads +- [X] [#307](https://github.com/kubernetes/ingress/pull/307) Add docs for body-size annotation +- [X] [#306](https://github.com/kubernetes/ingress/pull/306) modify nginx readme +- [X] [#304](https://github.com/kubernetes/ingress/pull/304) change 'buildSSPassthrouthUpstreams' to 'buildSSLPassthroughUpstreams' + + ### 0.9-beta.2 **Image:** `gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2` diff --git a/controllers/nginx/Makefile b/controllers/nginx/Makefile index bf22ee4ab..ac1300eb4 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.2 +RELEASE?=0.9.0-beta.3 PREFIX?=gcr.io/google_containers/nginx-ingress-controller GOOS?=linux DOCKER?=gcloud docker -- diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index ab12588bd..877dc152b 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -255,7 +255,7 @@ spec: spec: terminationGracePeriodSeconds: 60 containers: - - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2 + - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3 name: ingress-nginx imagePullPolicy: Always ports: diff --git a/examples/customization/configuration-snippets/nginx/nginx-ingress-controller.yaml b/examples/customization/configuration-snippets/nginx/nginx-ingress-controller.yaml index c4065804a..5786f03d9 100644 --- a/examples/customization/configuration-snippets/nginx/nginx-ingress-controller.yaml +++ b/examples/customization/configuration-snippets/nginx/nginx-ingress-controller.yaml @@ -19,7 +19,7 @@ spec: # hostNetwork: true terminationGracePeriodSeconds: 60 containers: - - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2 + - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3 name: nginx-ingress-controller readinessProbe: httpGet: diff --git a/examples/customization/custom-errors/nginx/rc-custom-errors.yaml b/examples/customization/custom-errors/nginx/rc-custom-errors.yaml index d26dcbd5e..3dfbe540c 100644 --- a/examples/customization/custom-errors/nginx/rc-custom-errors.yaml +++ b/examples/customization/custom-errors/nginx/rc-custom-errors.yaml @@ -16,7 +16,7 @@ spec: spec: terminationGracePeriodSeconds: 60 containers: - - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2 + - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3 name: nginx-ingress-lb imagePullPolicy: Always readinessProbe: diff --git a/examples/customization/custom-headers/nginx/nginx-ingress-controller.yaml b/examples/customization/custom-headers/nginx/nginx-ingress-controller.yaml index c4065804a..5786f03d9 100644 --- a/examples/customization/custom-headers/nginx/nginx-ingress-controller.yaml +++ b/examples/customization/custom-headers/nginx/nginx-ingress-controller.yaml @@ -19,7 +19,7 @@ spec: # hostNetwork: true terminationGracePeriodSeconds: 60 containers: - - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2 + - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3 name: nginx-ingress-controller readinessProbe: httpGet: diff --git a/examples/customization/custom-template/custom-template.yaml b/examples/customization/custom-template/custom-template.yaml index 168b56b50..d3ca02cb1 100644 --- a/examples/customization/custom-template/custom-template.yaml +++ b/examples/customization/custom-template/custom-template.yaml @@ -16,7 +16,7 @@ spec: spec: terminationGracePeriodSeconds: 60 containers: - - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2 + - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3 name: nginx-ingress-lb imagePullPolicy: Always readinessProbe: diff --git a/examples/daemonset/nginx/nginx-ingress-daemonset.yaml b/examples/daemonset/nginx/nginx-ingress-daemonset.yaml index 1b476d670..0db798c30 100644 --- a/examples/daemonset/nginx/nginx-ingress-daemonset.yaml +++ b/examples/daemonset/nginx/nginx-ingress-daemonset.yaml @@ -13,7 +13,7 @@ spec: spec: terminationGracePeriodSeconds: 60 containers: - - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2 + - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3 name: nginx-ingress-lb readinessProbe: httpGet: diff --git a/examples/deployment/nginx/kubeadm/nginx-ingress-controller.yaml b/examples/deployment/nginx/kubeadm/nginx-ingress-controller.yaml index f2ca1072e..11f95e901 100644 --- a/examples/deployment/nginx/kubeadm/nginx-ingress-controller.yaml +++ b/examples/deployment/nginx/kubeadm/nginx-ingress-controller.yaml @@ -71,7 +71,7 @@ spec: hostNetwork: true terminationGracePeriodSeconds: 60 containers: - - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2 + - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3 name: nginx-ingress-controller readinessProbe: httpGet: diff --git a/examples/deployment/nginx/nginx-ingress-controller.yaml b/examples/deployment/nginx/nginx-ingress-controller.yaml index b610d58f8..9ed25ad7f 100644 --- a/examples/deployment/nginx/nginx-ingress-controller.yaml +++ b/examples/deployment/nginx/nginx-ingress-controller.yaml @@ -19,7 +19,7 @@ spec: # hostNetwork: true terminationGracePeriodSeconds: 60 containers: - - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2 + - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3 name: nginx-ingress-controller readinessProbe: httpGet: diff --git a/examples/scaling-deployment/nginx/nginx-ingress-deployment.yaml b/examples/scaling-deployment/nginx/nginx-ingress-deployment.yaml index f0ee65b31..d0948773f 100644 --- a/examples/scaling-deployment/nginx/nginx-ingress-deployment.yaml +++ b/examples/scaling-deployment/nginx/nginx-ingress-deployment.yaml @@ -14,7 +14,7 @@ spec: spec: terminationGracePeriodSeconds: 60 containers: - - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2 + - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3 name: nginx-ingress-controller readinessProbe: httpGet: diff --git a/examples/static-ip/nginx/nginx-ingress-controller.yaml b/examples/static-ip/nginx/nginx-ingress-controller.yaml index d6eb1d512..1417a28eb 100644 --- a/examples/static-ip/nginx/nginx-ingress-controller.yaml +++ b/examples/static-ip/nginx/nginx-ingress-controller.yaml @@ -18,7 +18,7 @@ spec: # hostNetwork: true terminationGracePeriodSeconds: 60 containers: - - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2 + - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3 name: nginx-ingress-controller readinessProbe: httpGet: From 071ac585647839dfaadcdb829e9ec47c740728f4 Mon Sep 17 00:00:00 2001 From: Jeff Grafton Date: Tue, 14 Mar 2017 14:49:21 -0700 Subject: [PATCH 15/35] Fix a few bugs in the nginx-ingress-controller Makefile * make 'clean' use the new path to the built binary * make 'container' depend on 'build' --- controllers/nginx/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/nginx/Makefile b/controllers/nginx/Makefile index ac1300eb4..058760582 100644 --- a/controllers/nginx/Makefile +++ b/controllers/nginx/Makefile @@ -21,7 +21,7 @@ build: clean -ldflags "-s -w -X ${PKG}/pkg/version.RELEASE=${RELEASE} -X ${PKG}/pkg/version.COMMIT=${COMMIT} -X ${PKG}/pkg/version.REPO=${REPO_INFO}" \ -o rootfs/nginx-ingress-controller ${PKG}/pkg/cmd/controller -container: +container: build $(DOCKER) build --pull -t $(PREFIX):$(RELEASE) rootfs push: container @@ -50,4 +50,4 @@ vet: @go vet $(shell go list ${PKG}/... | grep -v vendor) clean: - rm -f nginx-ingress-controller + rm -f rootfs/nginx-ingress-controller From 98abd6dd110edd9f0557dc2a55a99dc61a5d5844 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Tue, 14 Mar 2017 22:22:02 -0300 Subject: [PATCH 16/35] Corrects the README header from Rewrite docs --- examples/rewrite/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/rewrite/README.md b/examples/rewrite/README.md index 66d7bb038..f934eb616 100644 --- a/examples/rewrite/README.md +++ b/examples/rewrite/README.md @@ -1,4 +1,4 @@ -# Sticky Session +# Rewrite This example demonstrates how to use the Rewrite annotations @@ -124,4 +124,4 @@ Content-Type: text/html Content-Length: 162 Location: http://stickyingress.example.com/app1 Connection: keep-alive -``` \ No newline at end of file +``` From 350c5f2c037f6db49bac60319075844e33d6aec1 Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Wed, 15 Mar 2017 08:23:25 -0300 Subject: [PATCH 17/35] Remove snake oil certificate generation --- controllers/nginx/rootfs/Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/controllers/nginx/rootfs/Dockerfile b/controllers/nginx/rootfs/Dockerfile index 6959d6bbc..dc114b925 100644 --- a/controllers/nginx/rootfs/Dockerfile +++ b/controllers/nginx/rootfs/Dockerfile @@ -16,10 +16,8 @@ FROM gcr.io/google_containers/nginx-slim:0.14 RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \ diffutils \ - ssl-cert \ --no-install-recommends \ - && rm -rf /var/lib/apt/lists/* \ - && make-ssl-cert generate-default-snakeoil --force-overwrite + && rm -rf /var/lib/apt/lists/* COPY . / From 3570d44370a5bf32f4e3e1a79c37fd00726a4722 Mon Sep 17 00:00:00 2001 From: Giancarlo Rubio Date: Wed, 15 Mar 2017 12:39:39 +0100 Subject: [PATCH 18/35] remove configmap validations . rollback #441, fix #443 --- core/pkg/ingress/controller/launch.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/core/pkg/ingress/controller/launch.go b/core/pkg/ingress/controller/launch.go index 144da3969..d532c0653 100644 --- a/core/pkg/ingress/controller/launch.go +++ b/core/pkg/ingress/controller/launch.go @@ -128,19 +128,6 @@ func NewIngressController(backend ingress.Controller) *GenericController { glog.Infof("service %v validated as source of Ingress status", *publishSvc) } - for _, configMap := range []string{*configMap, *tcpConfigMapName, *udpConfigMapName} { - - if configMap == "" { - continue - } - - _, err = k8s.IsValidConfigMap(kubeClient, configMap) - - if err != nil { - glog.Fatalf("%v", err) - } - } - if *watchNamespace != "" { _, err = k8s.IsValidNamespace(kubeClient, *watchNamespace) From 23c45340be3f92b0fe9d616ad31b63c017b21f6d Mon Sep 17 00:00:00 2001 From: Kirill Levin Date: Wed, 15 Mar 2017 20:45:21 +0300 Subject: [PATCH 19/35] fix nginx-udp-and-udp on same port --- controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl index 07a7e7921..73472122f 100644 --- a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl +++ b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl @@ -490,7 +490,7 @@ stream { # TCP services {{ range $i, $tcpServer := .TCPBackends }} - upstream {{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }} { + upstream tcp-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }} { {{ range $j, $endpoint := $tcpServer.Endpoints }} server {{ $endpoint.Address }}:{{ $endpoint.Port }}; {{ end }} @@ -498,22 +498,22 @@ stream { server { listen {{ $tcpServer.Port }}; - proxy_pass {{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }}; + proxy_pass tcp-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }}; } {{ end }} # UDP services {{ range $i, $udpServer := .UDPBackends }} - upstream {{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }} { + upstream udp-{{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }} { {{ range $j, $endpoint := $udpServer.Endpoints }} server {{ $endpoint.Address }}:{{ $endpoint.Port }}; {{ end }} } server { - listen {{ $udpServer.Port }}; + listen {{ $udpServer.Port }} udp; proxy_responses 1; - proxy_pass {{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }}; + proxy_pass udp-{{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }}; } {{ end }} } From 6f2532930812c86058f06a1929aeaa754b9853d9 Mon Sep 17 00:00:00 2001 From: Ricardo Pchevuzinske Katz Date: Wed, 15 Mar 2017 23:07:26 -0300 Subject: [PATCH 20/35] Changes the NGINX Rewrite Example location --- examples/rewrite/{ => nginx}/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/rewrite/{ => nginx}/README.md (100%) diff --git a/examples/rewrite/README.md b/examples/rewrite/nginx/README.md similarity index 100% rename from examples/rewrite/README.md rename to examples/rewrite/nginx/README.md From d82544fe8055da234e7ed681a7e8a5ca068cf6ec Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Thu, 16 Mar 2017 08:20:52 -0300 Subject: [PATCH 21/35] Avoid upstreams with multiple servers with the same port --- core/pkg/ingress/controller/controller.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/pkg/ingress/controller/controller.go b/core/pkg/ingress/controller/controller.go index bbb96df36..96c5800c5 100644 --- a/core/pkg/ingress/controller/controller.go +++ b/core/pkg/ingress/controller/controller.go @@ -991,6 +991,11 @@ func (ic *GenericController) getEndpoints( upsServers := []ingress.Endpoint{} + // avoid duplicated upstream servers when the service + // contains multiple port definitions sharing the same + // targetport. + adus := make(map[string]bool, 0) + for _, ss := range ep.Subsets { for _, epPort := range ss.Ports { @@ -1031,6 +1036,10 @@ func (ic *GenericController) getEndpoints( } for _, epAddress := range ss.Addresses { + ep := fmt.Sprintf("%v:%v", epAddress.IP, targetPort) + if _, exists := adus[ep]; exists { + continue + } ups := ingress.Endpoint{ Address: epAddress.IP, Port: fmt.Sprintf("%v", targetPort), @@ -1038,6 +1047,7 @@ func (ic *GenericController) getEndpoints( FailTimeout: hz.FailTimeout, } upsServers = append(upsServers, ups) + adus[ep] = true } } } From 18492c1384a5dcae07ce4dae76bebf1b4e854f81 Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Thu, 16 Mar 2017 12:07:07 -0300 Subject: [PATCH 22/35] Add information about SSL certificates in the default log level. --- core/pkg/ingress/controller/backend_ssl.go | 8 ++++---- core/pkg/ingress/controller/controller.go | 10 ++++++++++ core/pkg/ingress/controller/util.go | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/core/pkg/ingress/controller/backend_ssl.go b/core/pkg/ingress/controller/backend_ssl.go index e75d8ff0e..977484081 100644 --- a/core/pkg/ingress/controller/backend_ssl.go +++ b/core/pkg/ingress/controller/backend_ssl.go @@ -76,11 +76,11 @@ func (ic *GenericController) syncSecret(k interface{}) error { // no need to update return nil } - glog.V(3).Infof("updating secret %v/%v in the store", sec.Namespace, sec.Name) + glog.Infof("updating secret %v/%v in the local store", sec.Namespace, sec.Name) ic.sslCertTracker.Update(key, cert) return nil } - glog.V(3).Infof("adding secret %v/%v to the store", sec.Namespace, sec.Name) + glog.Infof("adding secret %v/%v to the local store", sec.Namespace, sec.Name) ic.sslCertTracker.Add(key, cert) return nil } @@ -106,10 +106,10 @@ func (ic *GenericController) getPemCertificate(secretName string) (*ingress.SSLC var s *ingress.SSLCert if okcert && okkey { - glog.V(3).Infof("found certificate and private key, configuring %v as a TLS Secret", secretName) + glog.Infof("found certificate and private key, configuring %v as a TLS Secret", secretName) s, err = ssl.AddOrUpdateCertAndKey(nsSecName, cert, key, ca) } else if ca != nil { - glog.V(3).Infof("found only ca.crt, configuring %v as an Certificate Authentication secret", secretName) + glog.Infof("found only ca.crt, configuring %v as an Certificate Authentication secret", secretName) s, err = ssl.AddCertAuth(nsSecName, ca) } else { return nil, fmt.Errorf("ko keypair or CA cert could be found in %v", secretName) diff --git a/core/pkg/ingress/controller/controller.go b/core/pkg/ingress/controller/controller.go index 96c5800c5..036e38d50 100644 --- a/core/pkg/ingress/controller/controller.go +++ b/core/pkg/ingress/controller/controller.go @@ -960,6 +960,12 @@ func (ic *GenericController) createServers(data []interface{}, } } + if tlsSecretName == "" { + glog.Warningf("ingress rule %v/%v for host %v does not contains a matching tls host", ing.Namespace, ing.Name, host) + glog.V(2).Infof("%v", ing.Spec.TLS) + continue + } + key := fmt.Sprintf("%v/%v", ing.Namespace, tlsSecretName) bc, exists := ic.sslCertTracker.Get(key) if exists { @@ -967,7 +973,11 @@ func (ic *GenericController) createServers(data []interface{}, if isHostValid(host, cert) { servers[host].SSLCertificate = cert.PemFileName servers[host].SSLPemChecksum = cert.PemSHA + } else { + glog.Warningf("ssl certificate %v does not contains a common name for host %v", key, host) } + } else { + glog.Warningf("ssl certificate \"%v\" does not exist in local store", key) } } } diff --git a/core/pkg/ingress/controller/util.go b/core/pkg/ingress/controller/util.go index 77b88ba0c..7f7db932e 100644 --- a/core/pkg/ingress/controller/util.go +++ b/core/pkg/ingress/controller/util.go @@ -46,7 +46,7 @@ func isHostValid(host string, cert *ingress.SSLCert) bool { return false } for _, cn := range cert.CN { - if matchHostnames(cn, host) { + if matchHostnames(cn, strings.ToLower(host)) { return true } } From 37bdb3952e090e50f44207ad0e54b1f2a4ef1055 Mon Sep 17 00:00:00 2001 From: chentao1596 Date: Fri, 6 Jan 2017 16:12:25 +0800 Subject: [PATCH 23/35] fix all go style mistakes about fmt.Errorf --- controllers/gce/backends/backends.go | 2 +- controllers/gce/backends/fakes.go | 6 +++--- controllers/gce/controller/controller.go | 6 +++--- controllers/gce/controller/tls.go | 6 +++--- controllers/gce/controller/utils.go | 12 ++++++------ controllers/gce/firewalls/fakes.go | 6 +++--- controllers/gce/healthchecks/fakes.go | 6 +++--- controllers/gce/instances/fakes.go | 4 ++-- controllers/gce/loadbalancers/fakes.go | 14 +++++++------- controllers/gce/loadbalancers/loadbalancers.go | 16 ++++++++-------- controllers/gce/main.go | 2 +- controllers/gce/storage/configmaps.go | 6 +++--- controllers/gce/utils/utils.go | 4 ++-- controllers/nginx/pkg/cmd/controller/nginx.go | 2 +- controllers/nginx/pkg/metric/collector/status.go | 2 +- core/pkg/net/ssl/ssl.go | 14 +++++++------- hack/e2e.go | 2 +- 17 files changed, 55 insertions(+), 55 deletions(-) diff --git a/controllers/gce/backends/backends.go b/controllers/gce/backends/backends.go index 07f0b3fae..81edc32e3 100644 --- a/controllers/gce/backends/backends.go +++ b/controllers/gce/backends/backends.go @@ -119,7 +119,7 @@ func NewBackendPool( func(i interface{}) (string, error) { bs := i.(*compute.BackendService) if !namer.NameBelongsToCluster(bs.Name) { - return "", fmt.Errorf("Unrecognized name %v", bs.Name) + return "", fmt.Errorf("unrecognized name %v", bs.Name) } port, err := namer.BePort(bs.Name) if err != nil { diff --git a/controllers/gce/backends/fakes.go b/controllers/gce/backends/fakes.go index bb2b031f0..6ad7460f5 100644 --- a/controllers/gce/backends/fakes.go +++ b/controllers/gce/backends/fakes.go @@ -47,7 +47,7 @@ func (f *FakeBackendServices) GetBackendService(name string) (*compute.BackendSe f.calls = append(f.calls, utils.Get) obj, exists, err := f.backendServices.GetByKey(name) if !exists { - return nil, fmt.Errorf("Backend service %v not found", name) + return nil, fmt.Errorf("backend service %v not found", name) } if err != nil { return nil, err @@ -57,7 +57,7 @@ func (f *FakeBackendServices) GetBackendService(name string) (*compute.BackendSe if name == svc.Name { return svc, nil } - return nil, fmt.Errorf("Backend service %v not found", name) + return nil, fmt.Errorf("backend service %v not found", name) } // CreateBackendService fakes backend service creation. @@ -77,7 +77,7 @@ func (f *FakeBackendServices) DeleteBackendService(name string) error { f.calls = append(f.calls, utils.Delete) svc, exists, err := f.backendServices.GetByKey(name) if !exists { - return fmt.Errorf("Backend service %v not found", name) + return fmt.Errorf("backend service %v not found", name) } if err != nil { return err diff --git a/controllers/gce/controller/controller.go b/controllers/gce/controller/controller.go index 69f6a2533..3a039222b 100644 --- a/controllers/gce/controller/controller.go +++ b/controllers/gce/controller/controller.go @@ -290,7 +290,7 @@ func (lbc *LoadBalancerController) storesSynced() bool { func (lbc *LoadBalancerController) sync(key string) (err error) { if !lbc.hasSynced() { time.Sleep(storeSyncPollPeriod) - return fmt.Errorf("Waiting for stores to sync") + return fmt.Errorf("waiting for stores to sync") } glog.V(3).Infof("Syncing %v", key) @@ -326,7 +326,7 @@ func (lbc *LoadBalancerController) sync(key string) (err error) { defer func() { if deferErr := lbc.CloudClusterManager.GC(lbNames, nodePorts); deferErr != nil { - err = fmt.Errorf("Error during sync %v, error during GC %v", err, deferErr) + err = fmt.Errorf("error during sync %v, error during GC %v", err, deferErr) } glog.V(3).Infof("Finished syncing %v", key) }() @@ -343,7 +343,7 @@ func (lbc *LoadBalancerController) sync(key string) (err error) { if ingExists { lbc.recorder.Eventf(obj.(*extensions.Ingress), api.EventTypeWarning, eventMsg, err.Error()) } else { - err = fmt.Errorf("%v Error: %v", eventMsg, err) + err = fmt.Errorf("%v, error: %v", eventMsg, err) } syncError = err } diff --git a/controllers/gce/controller/tls.go b/controllers/gce/controller/tls.go index b8cb7a2e7..70bf7e00c 100644 --- a/controllers/gce/controller/tls.go +++ b/controllers/gce/controller/tls.go @@ -65,11 +65,11 @@ func (t *apiServerTLSLoader) load(ing *extensions.Ingress) (*loadbalancers.TLSCe } cert, ok := secret.Data[api.TLSCertKey] if !ok { - return nil, fmt.Errorf("Secret %v has no private key", secretName) + return nil, fmt.Errorf("secret %v has no private key", secretName) } key, ok := secret.Data[api.TLSPrivateKeyKey] if !ok { - return nil, fmt.Errorf("Secret %v has no cert", secretName) + return nil, fmt.Errorf("secret %v has no cert", secretName) } certs := &loadbalancers.TLSCerts{Key: string(key), Cert: string(cert)} if err := t.validate(certs); err != nil { @@ -95,5 +95,5 @@ func (f *fakeTLSSecretLoader) load(ing *extensions.Ingress) (*loadbalancers.TLSC return cert, nil } } - return nil, fmt.Errorf("Couldn't find secret for ingress %v", ing.Name) + return nil, fmt.Errorf("couldn't find secret for ingress %v", ing.Name) } diff --git a/controllers/gce/controller/utils.go b/controllers/gce/controller/utils.go index b57020cc3..7efc6cd56 100644 --- a/controllers/gce/controller/utils.go +++ b/controllers/gce/controller/utils.go @@ -233,7 +233,7 @@ func (s *StoreToIngressLister) GetServiceIngress(svc *api.Service) (ings []exten } } if len(ings) == 0 { - err = fmt.Errorf("No ingress for service %v", svc.Name) + err = fmt.Errorf("no ingress for service %v", svc.Name) } return } @@ -315,7 +315,7 @@ func (t *GCETranslator) toGCEBackend(be *extensions.IngressBackend, ns string) ( backend, err := t.CloudClusterManager.backendPool.Get(int64(port)) if err != nil { return nil, fmt.Errorf( - "No GCE backend exists for port %v, kube backend %+v", port, be) + "no GCE backend exists for port %v, kube backend %+v", port, be) } return backend, nil } @@ -332,7 +332,7 @@ func (t *GCETranslator) getServiceNodePort(be extensions.IngressBackend, namespa }) if !exists { return invalidPort, errorNodePortNotFound{be, fmt.Errorf( - "Service %v/%v not found in store", namespace, be.ServiceName)} + "service %v/%v not found in store", namespace, be.ServiceName)} } if err != nil { return invalidPort, errorNodePortNotFound{be, err} @@ -356,7 +356,7 @@ func (t *GCETranslator) getServiceNodePort(be extensions.IngressBackend, namespa return nodePort, nil } return invalidPort, errorNodePortNotFound{be, fmt.Errorf( - "Could not find matching nodeport from service.")} + "could not find matching nodeport from service")} } // toNodePorts converts a pathlist to a flat list of nodeports. @@ -374,7 +374,7 @@ func (t *GCETranslator) toNodePorts(ings *extensions.IngressList) []int64 { } for _, rule := range ing.Spec.Rules { if rule.HTTP == nil { - glog.Errorf("Ignoring non http Ingress rule.") + glog.Errorf("ignoring non http Ingress rule") continue } for _, path := range rule.HTTP.Paths { @@ -411,7 +411,7 @@ func (t *GCETranslator) GetZoneForNode(name string) (string, error) { return getZone(n), nil } } - return "", fmt.Errorf("Node not found %v", name) + return "", fmt.Errorf("node not found %v", name) } // ListZones returns a list of zones this Kubernetes cluster spans. diff --git a/controllers/gce/firewalls/fakes.go b/controllers/gce/firewalls/fakes.go index 3479d83d1..71c90c321 100644 --- a/controllers/gce/firewalls/fakes.go +++ b/controllers/gce/firewalls/fakes.go @@ -35,7 +35,7 @@ func (f *fakeFirewallRules) GetFirewall(name string) (*compute.Firewall, error) return rule, nil } } - return nil, fmt.Errorf("Firewall rule %v not found.", name) + return nil, fmt.Errorf("firewall rule %v not found", name) } func (f *fakeFirewallRules) CreateFirewall(name, msgTag string, srcRange netset.IPNet, ports []int64, hosts []string) error { @@ -66,7 +66,7 @@ func (f *fakeFirewallRules) DeleteFirewall(name string) error { firewalls = append(firewalls, rule) } if !exists { - return fmt.Errorf("Failed to find health check %v", name) + return fmt.Errorf("failed to find health check %v", name) } f.fw = firewalls return nil @@ -95,7 +95,7 @@ func (f *fakeFirewallRules) UpdateFirewall(name, msgTag string, srcRange netset. if exists { return nil } - return fmt.Errorf("Update failed for rule %v, srcRange %v ports %v, rule not found", name, srcRange, ports) + return fmt.Errorf("update failed for rule %v, srcRange %v ports %v, rule not found", name, srcRange, ports) } // NewFakeFirewallRules creates a fake for firewall rules. diff --git a/controllers/gce/healthchecks/fakes.go b/controllers/gce/healthchecks/fakes.go index 900b73023..18984d122 100644 --- a/controllers/gce/healthchecks/fakes.go +++ b/controllers/gce/healthchecks/fakes.go @@ -60,7 +60,7 @@ func (f *FakeHealthChecks) GetHttpHealthCheck(name string) (*compute.HttpHealthC return h, nil } } - return nil, fmt.Errorf("Health check %v not found.", name) + return nil, fmt.Errorf("health check %v not found", name) } // DeleteHttpHealthCheck fakes out deleting a http health check. @@ -75,7 +75,7 @@ func (f *FakeHealthChecks) DeleteHttpHealthCheck(name string) error { healthChecks = append(healthChecks, h) } if !exists { - return fmt.Errorf("Failed to find health check %v", name) + return fmt.Errorf("failed to find health check %v", name) } f.hc = healthChecks return nil @@ -94,7 +94,7 @@ func (f *FakeHealthChecks) UpdateHttpHealthCheck(hc *compute.HttpHealthCheck) er } } if !found { - return fmt.Errorf("Cannot update a non-existent health check %v", hc.Name) + return fmt.Errorf("cannot update a non-existent health check %v", hc.Name) } f.hc = healthChecks return nil diff --git a/controllers/gce/instances/fakes.go b/controllers/gce/instances/fakes.go index 94e22ced9..df2ee26fa 100644 --- a/controllers/gce/instances/fakes.go +++ b/controllers/gce/instances/fakes.go @@ -75,7 +75,7 @@ func (f *FakeInstanceGroups) GetInstanceGroup(name, zone string) (*compute.Insta } } // TODO: Return googleapi 404 error - return nil, fmt.Errorf("Instance group %v not found", name) + return nil, fmt.Errorf("instance group %v not found", name) } // CreateInstanceGroup fakes instance group creation. @@ -97,7 +97,7 @@ func (f *FakeInstanceGroups) DeleteInstanceGroup(name, zone string) error { newGroups = append(newGroups, ig) } if !found { - return fmt.Errorf("Instance Group %v not found", name) + return fmt.Errorf("instance group %v not found", name) } f.instanceGroups = newGroups return nil diff --git a/controllers/gce/loadbalancers/fakes.go b/controllers/gce/loadbalancers/fakes.go index b167a9ae1..6dfdcd941 100644 --- a/controllers/gce/loadbalancers/fakes.go +++ b/controllers/gce/loadbalancers/fakes.go @@ -109,7 +109,7 @@ func (f *FakeLoadBalancers) GetGlobalForwardingRule(name string) (*compute.Forwa return f.Fw[i], nil } } - return nil, fmt.Errorf("Forwarding rule %v not found", name) + return nil, fmt.Errorf("forwarding rule %v not found", name) } // CreateGlobalForwardingRule fakes forwarding rule creation. @@ -176,7 +176,7 @@ func (f *FakeLoadBalancers) GetUrlMap(name string) (*compute.UrlMap, error) { return f.Um[i], nil } } - return nil, fmt.Errorf("Url Map %v not found", name) + return nil, fmt.Errorf("url map %v not found", name) } // CreateUrlMap fakes url-map creation. @@ -226,7 +226,7 @@ func (f *FakeLoadBalancers) GetTargetHttpProxy(name string) (*compute.TargetHttp return f.Tp[i], nil } } - return nil, fmt.Errorf("Targetproxy %v not found", name) + return nil, fmt.Errorf("target http proxy %v not found", name) } // CreateTargetHttpProxy fakes creating a target http proxy. @@ -275,7 +275,7 @@ func (f *FakeLoadBalancers) GetTargetHttpsProxy(name string) (*compute.TargetHtt return f.Tps[i], nil } } - return nil, fmt.Errorf("Targetproxy %v not found", name) + return nil, fmt.Errorf("target https proxy %v not found", name) } // CreateTargetHttpsProxy fakes creating a target http proxy. @@ -326,7 +326,7 @@ func (f *FakeLoadBalancers) SetSslCertificateForTargetHttpsProxy(proxy *compute. } } if !found { - return fmt.Errorf("Failed to find proxy %v", proxy.Name) + return fmt.Errorf("failed to find proxy %v", proxy.Name) } return nil } @@ -415,7 +415,7 @@ func (f *FakeLoadBalancers) GetGlobalStaticIP(name string) (*compute.Address, er return f.IP[i], nil } } - return nil, fmt.Errorf("Static IP %v not found", name) + return nil, fmt.Errorf("static IP %v not found", name) } // DeleteGlobalStaticIP fakes out static IP deletion. @@ -441,7 +441,7 @@ func (f *FakeLoadBalancers) GetSslCertificate(name string) (*compute.SslCertific return f.Certs[i], nil } } - return nil, fmt.Errorf("Cert %v not found", name) + return nil, fmt.Errorf("cert %v not found", name) } // CreateSslCertificate fakes out certificate creation. diff --git a/controllers/gce/loadbalancers/loadbalancers.go b/controllers/gce/loadbalancers/loadbalancers.go index 9688a4cc0..7e04fb2b0 100644 --- a/controllers/gce/loadbalancers/loadbalancers.go +++ b/controllers/gce/loadbalancers/loadbalancers.go @@ -106,7 +106,7 @@ func (l *L7s) Get(name string) (*L7, error) { name = l.namer.LBName(name) lb, exists := l.snapshotter.Get(name) if !exists { - return nil, fmt.Errorf("Loadbalancer %v not in pool", name) + return nil, fmt.Errorf("loadbalancer %v not in pool", name) } return lb.(*L7), nil } @@ -292,7 +292,7 @@ type L7 struct { func (l *L7) checkUrlMap(backend *compute.BackendService) (err error) { if l.glbcDefaultBackend == nil { - return fmt.Errorf("Cannot create urlmap without default backend.") + return fmt.Errorf("cannot create urlmap without default backend") } urlMapName := l.namer.Truncate(fmt.Sprintf("%v-%v", urlMapPrefix, l.Name)) urlMap, _ := l.cloud.GetUrlMap(urlMapName) @@ -313,7 +313,7 @@ func (l *L7) checkUrlMap(backend *compute.BackendService) (err error) { func (l *L7) checkProxy() (err error) { if l.um == nil { - return fmt.Errorf("Cannot create proxy without urlmap.") + return fmt.Errorf("cannot create proxy without urlmap") } proxyName := l.namer.Truncate(fmt.Sprintf("%v-%v", targetProxyPrefix, l.Name)) proxy, _ := l.cloud.GetTargetHttpProxy(proxyName) @@ -362,7 +362,7 @@ func (l *L7) checkSSLCert() (err error) { return err } if cert == nil { - return fmt.Errorf("Cannot find existing sslCertificate %v for %v", certName, l.Name) + return fmt.Errorf("cannot find existing sslCertificate %v for %v", certName, l.Name) } glog.Infof("Using existing sslCertificate %v for %v", certName, l.Name) @@ -429,7 +429,7 @@ func (l *L7) checkHttpsProxy() (err error) { return nil } if l.um == nil { - return fmt.Errorf("No UrlMap for %v, will not create HTTPS proxy.", l.Name) + return fmt.Errorf("no UrlMap for %v, will not create HTTPS proxy", l.Name) } proxyName := l.namer.Truncate(fmt.Sprintf("%v-%v", targetHTTPSProxyPrefix, l.Name)) proxy, _ := l.cloud.GetTargetHttpsProxy(proxyName) @@ -535,7 +535,7 @@ func (l *L7) getEffectiveIP() (string, bool) { func (l *L7) checkHttpForwardingRule() (err error) { if l.tp == nil { - return fmt.Errorf("Cannot create forwarding rule without proxy.") + return fmt.Errorf("cannot create forwarding rule without proxy") } name := l.namer.Truncate(fmt.Sprintf("%v-%v", forwardingRulePrefix, l.Name)) address, _ := l.getEffectiveIP() @@ -565,7 +565,7 @@ func (l *L7) checkHttpsForwardingRule() (err error) { // checkStaticIP reserves a static IP allocated to the Forwarding Rule. func (l *L7) checkStaticIP() (err error) { if l.fw == nil || l.fw.IPAddress == "" { - return fmt.Errorf("Will not create static IP without a forwarding rule.") + return fmt.Errorf("will not create static IP without a forwarding rule") } // Don't manage staticIPs if the user has specified an IP. if address, manageStaticIP := l.getEffectiveIP(); !manageStaticIP { @@ -704,7 +704,7 @@ func getNameForPathMatcher(hostRule string) string { // pathmatcher of the host. func (l *L7) UpdateUrlMap(ingressRules utils.GCEURLMap) error { if l.um == nil { - return fmt.Errorf("Cannot add url without an urlmap.") + return fmt.Errorf("cannot add url without an urlmap") } glog.V(3).Infof("Updating urlmap for l7 %v", l.Name) diff --git a/controllers/gce/main.go b/controllers/gce/main.go index b8afbf9ab..a306956a2 100644 --- a/controllers/gce/main.go +++ b/controllers/gce/main.go @@ -316,7 +316,7 @@ func useDefaultOrLookupVault(cfgVault *storage.ConfigMapVault, cm_key, default_n // 2. No such key in config map - found=false, err=nil // 3. Apiserver flake - found=false, err!=nil // It is not safe to proceed in 3. - return "", fmt.Errorf("Failed to retrieve %v: %v, returning empty name", cm_key, err) + return "", fmt.Errorf("failed to retrieve %v: %v, returning empty name", cm_key, err) } else if !found { // Not found but safe to proceed. return "", nil diff --git a/controllers/gce/storage/configmaps.go b/controllers/gce/storage/configmaps.go index 6af08b65d..ace030b9f 100644 --- a/controllers/gce/storage/configmaps.go +++ b/controllers/gce/storage/configmaps.go @@ -95,12 +95,12 @@ func (c *ConfigMapVault) Put(key, val string) error { glog.Infof("Configmap %v will be updated with %v = %v", cfgMapKey, key, val) } if err := c.ConfigMapStore.Update(apiObj); err != nil { - return fmt.Errorf("Failed to update %v: %v", cfgMapKey, err) + return fmt.Errorf("failed to update %v: %v", cfgMapKey, err) } } else { apiObj.Data = map[string]string{key: val} if err := c.ConfigMapStore.Add(apiObj); err != nil { - return fmt.Errorf("Failed to add %v: %v", cfgMapKey, err) + return fmt.Errorf("failed to add %v: %v", cfgMapKey, err) } } glog.Infof("Successfully stored key %v = %v in config map %v", key, val, cfgMapKey) @@ -176,7 +176,7 @@ func (a *APIServerConfigMapStore) Delete(obj interface{}) error { func (a *APIServerConfigMapStore) GetByKey(key string) (item interface{}, exists bool, err error) { nsName := strings.Split(key, "/") if len(nsName) != 2 { - return nil, false, fmt.Errorf("Failed to get key %v, unexpecte format, expecting ns/name", key) + return nil, false, fmt.Errorf("failed to get key %v, unexpecte format, expecting ns/name", key) } ns, name := nsName[0], nsName[1] cfg, err := a.client.Core().ConfigMaps(ns).Get(name) diff --git a/controllers/gce/utils/utils.go b/controllers/gce/utils/utils.go index 9d5dbfad1..1ed36769f 100644 --- a/controllers/gce/utils/utils.go +++ b/controllers/gce/utils/utils.go @@ -223,11 +223,11 @@ func (n *Namer) BePort(beName string) (string, error) { } match := r.FindStringSubmatch(beName) if len(match) < 2 { - return "", fmt.Errorf("Unable to lookup port for %v", beName) + return "", fmt.Errorf("unable to lookup port for %v", beName) } _, err = strconv.Atoi(match[1]) if err != nil { - return "", fmt.Errorf("Unexpected regex match: %v", beName) + return "", fmt.Errorf("unexpected regex match: %v", beName) } return match[1], nil } diff --git a/controllers/nginx/pkg/cmd/controller/nginx.go b/controllers/nginx/pkg/cmd/controller/nginx.go index 1bd7ede60..8e6873c50 100644 --- a/controllers/nginx/pkg/cmd/controller/nginx.go +++ b/controllers/nginx/pkg/cmd/controller/nginx.go @@ -441,7 +441,7 @@ func (n NGINXController) Check(_ *http.Request) error { } defer res.Body.Close() if res.StatusCode != 200 { - return fmt.Errorf("Ingress controller is not healthy") + return fmt.Errorf("ingress controller is not healthy") } return nil } diff --git a/controllers/nginx/pkg/metric/collector/status.go b/controllers/nginx/pkg/metric/collector/status.go index 1a0fcaf0e..361838a31 100644 --- a/controllers/nginx/pkg/metric/collector/status.go +++ b/controllers/nginx/pkg/metric/collector/status.go @@ -138,7 +138,7 @@ func (bit BoolToFloat64) UnmarshalJSON(data []byte) error { } else if asString == "0" || asString == "false" { bit = 0 } else { - return fmt.Errorf(fmt.Sprintf("Boolean unmarshal error: invalid input %s", asString)) + return fmt.Errorf(fmt.Sprintf("boolean unmarshal error: invalid input %s", asString)) } return nil } diff --git a/core/pkg/net/ssl/ssl.go b/core/pkg/net/ssl/ssl.go index c758423fc..70ed50434 100644 --- a/core/pkg/net/ssl/ssl.go +++ b/core/pkg/net/ssl/ssl.go @@ -75,13 +75,13 @@ func AddOrUpdateCertAndKey(name string, cert, key, ca []byte) (*ingress.SSLCert, pemBlock, _ := pem.Decode(pemCerts) if pemBlock == nil { _ = os.Remove(tempPemFile.Name()) - return nil, fmt.Errorf("No valid PEM formatted block found") + return nil, fmt.Errorf("no valid PEM formatted block found") } // If the file does not start with 'BEGIN CERTIFICATE' it's invalid and must not be used. if pemBlock.Type != "CERTIFICATE" { _ = os.Remove(tempPemFile.Name()) - return nil, fmt.Errorf("Certificate %v contains invalid data, and must be created with 'kubectl create secret tls'", name) + return nil, fmt.Errorf("certificate %v contains invalid data, and must be created with 'kubectl create secret tls'", name) } pemCert, err := x509.ParseCertificate(pemBlock.Bytes) @@ -115,7 +115,7 @@ func AddOrUpdateCertAndKey(name string, cert, key, ca []byte) (*ingress.SSLCert, caFile, err := os.OpenFile(pemFileName, os.O_RDWR|os.O_APPEND, 0600) if err != nil { - return nil, fmt.Errorf("Could not open file %v for writing additional CA chains: %v", pemFileName, err) + return nil, fmt.Errorf("could not open file %v for writing additional CA chains: %v", pemFileName, err) } defer caFile.Close() @@ -150,11 +150,11 @@ func AddCertAuth(name string, ca []byte) (*ingress.SSLCert, error) { pemCABlock, _ := pem.Decode(ca) if pemCABlock == nil { - return nil, fmt.Errorf("No valid PEM formatted block found") + return nil, fmt.Errorf("no valid PEM formatted block found") } // If the first certificate does not start with 'BEGIN CERTIFICATE' it's invalid and must not be used. if pemCABlock.Type != "CERTIFICATE" { - return nil, fmt.Errorf("CA File %v contains invalid data, and must be created only with PEM formated certificates", name) + return nil, fmt.Errorf("CA file %v contains invalid data, and must be created only with PEM formated certificates", name) } _, err := x509.ParseCertificate(pemCABlock.Bytes) @@ -206,13 +206,13 @@ func AddOrUpdateDHParam(name string, dh []byte) (string, error) { pemBlock, _ := pem.Decode(pemCerts) if pemBlock == nil { _ = os.Remove(tempPemFile.Name()) - return "", fmt.Errorf("No valid PEM formatted block found") + return "", fmt.Errorf("no valid PEM formatted block found") } // If the file does not start with 'BEGIN DH PARAMETERS' it's invalid and must not be used. if pemBlock.Type != "DH PARAMETERS" { _ = os.Remove(tempPemFile.Name()) - return "", fmt.Errorf("Certificate %v contains invalid data", name) + return "", fmt.Errorf("certificate %v contains invalid data", name) } err = os.Rename(tempPemFile.Name(), pemFileName) diff --git a/hack/e2e.go b/hack/e2e.go index 65dc71cd1..be9f2aa28 100644 --- a/hack/e2e.go +++ b/hack/e2e.go @@ -234,7 +234,7 @@ func getDeployer() (deployer, error) { case "bash": return bash{}, nil default: - return nil, fmt.Errorf("Unknown deployment strategy %q", *deployment) + return nil, fmt.Errorf("unknown deployment strategy %q", *deployment) } } From ee63e4576da58e8ebb69d5efe4fe5b149bb5d633 Mon Sep 17 00:00:00 2001 From: caiyixiang Date: Fri, 17 Mar 2017 17:14:35 +0800 Subject: [PATCH 24/35] add scaling haproxy --- examples/README.md | 4 +- examples/scaling-deployment/haproxy/README.md | 65 +++++++++++++++++++ .../haproxy/default-backend.yaml | 49 ++++++++++++++ .../haproxy/haproxy-ingress-deployment.yaml | 39 +++++++++++ 4 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 examples/scaling-deployment/haproxy/README.md create mode 100644 examples/scaling-deployment/haproxy/default-backend.yaml create mode 100644 examples/scaling-deployment/haproxy/haproxy-ingress-deployment.yaml diff --git a/examples/README.md b/examples/README.md index 69288dd45..997a64561 100644 --- a/examples/README.md +++ b/examples/README.md @@ -28,8 +28,8 @@ Re-encrypty | terminate, apply routing rules, re-encrypt | nginx | Advanced Name | Description | Platform | Complexity Level -----| ----------- | ---------- | ---------------- -Daemonset | run multiple controllers in a daemonset | nginx | Intermediate -Deployment | run multiple controllers as a deployment | nginx | Intermediate +Daemonset | run multiple controllers in a daemonset | nginx/haproxy | Intermediate +Deployment | run multiple controllers as a deployment | nginx/haproxy | Intermediate Multi-zone | bridge different zones in a single cluster | gce | Intermediate Static-ip | a single ingress gets a single static ip | * | Intermediate Geo-routing | route to geographically closest endpoint | nginx | Advanced diff --git a/examples/scaling-deployment/haproxy/README.md b/examples/scaling-deployment/haproxy/README.md new file mode 100644 index 000000000..463550d72 --- /dev/null +++ b/examples/scaling-deployment/haproxy/README.md @@ -0,0 +1,65 @@ +# Deploying multi Haproxy Ingress Controllers + +This example aims to demonstrate the Deployment of multi haproxy ingress controllers. + +## Prerequisites + +This ingress controller doesn't yet have support for +[ingress classes](/examples/PREREQUISITES.md#ingress-class). You MUST turn +down any existing ingress controllers before running HAProxy Ingress controller or +they will fight for Ingresses. This includes any cloudprovider controller. + +This document has also the following prerequisites: + +* Create a [TLS secret](/examples/PREREQUISITES.md#tls-certificates) named `tls-secret` to be used as default TLS certificate + +Creating the TLS secret: + +```console +$ openssl req \ + -x509 -newkey rsa:2048 -nodes -days 365 \ + -keyout tls.key -out tls.crt -subj '/CN=localhost' +$ kubectl create secret tls tls-secret --cert=tls.crt --key=tls.key +$ rm -v tls.crt tls.key +``` + +## Default Backend + +The default backend is a service of handling all url paths and hosts the haproxy controller doesn't understand. Deploy the default-http-backend as follow: + +```console +$ kubectl create -f default-backend.yaml +deployment "default-http-backend" created +service "default-http-backend" created + +$ kubectl get svc +NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE +default-http-backend 192.168.3.4 80/TCP 30m + +$ kubectl get pods +NAME READY STATUS RESTARTS AGE +default-http-backend-q5sb6 1/1 Running 0 30m +``` + +## Ingress Deployment + +Deploy the Deployment of multi controllers as follows: + +```console +$ kubectl apply -f haproxy-ingress-deployment.yaml +deployment "haproxy-ingress" created +``` + +Check if the controller was successfully deployed: +```console +$ kubectl get deployment +NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE +default-http-backend 1 1 1 1 30m +haproxy-ingress 2 2 2 2 45s + +$ kubectl get pods +NAME READY STATUS RESTARTS AGE +default-http-backend-q5sb6 1/1 Running 0 35m +haproxy-ingress-1779899633-k045t 1/1 Running 0 1m +haproxy-ingress-1779899633-mhthv 1/1 Running 0 1m +``` diff --git a/examples/scaling-deployment/haproxy/default-backend.yaml b/examples/scaling-deployment/haproxy/default-backend.yaml new file mode 100644 index 000000000..739ae2758 --- /dev/null +++ b/examples/scaling-deployment/haproxy/default-backend.yaml @@ -0,0 +1,49 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: default-http-backend + labels: + k8s-app: default-http-backend +spec: + replicas: 1 + template: + metadata: + labels: + k8s-app: default-http-backend + spec: + terminationGracePeriodSeconds: 60 + containers: + - name: default-http-backend + # Any image is permissable as long as: + # 1. It serves a 404 page at / + # 2. It serves 200 on a /healthz endpoint + image: gcr.io/google_containers/defaultbackend:1.0 + livenessProbe: + httpGet: + path: /healthz + port: 8080 + scheme: HTTP + initialDelaySeconds: 30 + timeoutSeconds: 5 + ports: + - containerPort: 8080 + resources: + limits: + cpu: 10m + memory: 20Mi + requests: + cpu: 10m + memory: 20Mi +--- +apiVersion: v1 +kind: Service +metadata: + name: default-http-backend + labels: + k8s-app: default-http-backend +spec: + ports: + - port: 80 + targetPort: 8080 + selector: + k8s-app: default-http-backend diff --git a/examples/scaling-deployment/haproxy/haproxy-ingress-deployment.yaml b/examples/scaling-deployment/haproxy/haproxy-ingress-deployment.yaml new file mode 100644 index 000000000..357ed6387 --- /dev/null +++ b/examples/scaling-deployment/haproxy/haproxy-ingress-deployment.yaml @@ -0,0 +1,39 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + labels: + run: haproxy-ingress + name: haproxy-ingress +spec: + replicas: 2 + selector: + matchLabels: + run: haproxy-ingress + template: + metadata: + labels: + run: haproxy-ingress + spec: + containers: + - name: haproxy-ingress + image: quay.io/jcmoraisjr/haproxy-ingress + imagePullPolicy: IfNotPresent + args: + - --default-backend-service=default/default-http-backend + - --default-ssl-certificate=default/tls-secret + ports: + - name: http + containerPort: 80 + - name: https + containerPort: 443 + - name: stat + containerPort: 1936 + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace From 3706f3263969ae5ae60fcf610125fe9aef3a2621 Mon Sep 17 00:00:00 2001 From: Nick Sardo Date: Mon, 20 Mar 2017 16:36:18 -0700 Subject: [PATCH 25/35] git ignore glbc --- controllers/gce/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 controllers/gce/.gitignore diff --git a/controllers/gce/.gitignore b/controllers/gce/.gitignore new file mode 100644 index 000000000..f83466729 --- /dev/null +++ b/controllers/gce/.gitignore @@ -0,0 +1 @@ +glbc From 6a38a1ac3744a597b2934167bf749f6885ae3bc5 Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Mon, 20 Mar 2017 18:22:06 -0400 Subject: [PATCH 26/35] Adding Prometheus metrics scrape annotations Allow Prometheus automatic discovery of nginx metrics endpoint Fixed https://github.com/kubernetes/ingress/issues/464 --- examples/daemonset/nginx/nginx-ingress-daemonset.yaml | 3 +++ examples/deployment/nginx/nginx-ingress-controller.yaml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/examples/daemonset/nginx/nginx-ingress-daemonset.yaml b/examples/daemonset/nginx/nginx-ingress-daemonset.yaml index 0db798c30..f785ff4ec 100644 --- a/examples/daemonset/nginx/nginx-ingress-daemonset.yaml +++ b/examples/daemonset/nginx/nginx-ingress-daemonset.yaml @@ -10,6 +10,9 @@ spec: metadata: labels: name: nginx-ingress-lb + annotations: + prometheus.io/port: '10254' + prometheus.io/scrape: 'true' spec: terminationGracePeriodSeconds: 60 containers: diff --git a/examples/deployment/nginx/nginx-ingress-controller.yaml b/examples/deployment/nginx/nginx-ingress-controller.yaml index 9ed25ad7f..63705a6ee 100644 --- a/examples/deployment/nginx/nginx-ingress-controller.yaml +++ b/examples/deployment/nginx/nginx-ingress-controller.yaml @@ -11,6 +11,9 @@ spec: metadata: labels: k8s-app: nginx-ingress-controller + annotations: + prometheus.io/port: '10254' + prometheus.io/scrape: 'true' spec: # hostNetwork makes it possible to use ipv6 and to preserve the source IP correctly regardless of docker configuration # however, it is not a hard dependency of the nginx-ingress-controller itself and it may cause issues if port 10254 already is taken on the host From 1f1829f42bf18ef433f585efc5cbd8fba4597416 Mon Sep 17 00:00:00 2001 From: zoues Date: Tue, 21 Mar 2017 23:29:57 +0800 Subject: [PATCH 27/35] add custom vts metrics example --- .../custom-vts-metrics/nginx/README.md | 74 +++++++++++++++++++ .../nginx/default-backend.yaml | 51 +++++++++++++ .../nginx/nginx-ingress-controller.yaml | 56 ++++++++++++++ .../nginx/nginx-vts-metrics-conf.yaml | 7 ++ 4 files changed, 188 insertions(+) create mode 100644 examples/customization/custom-vts-metrics/nginx/README.md create mode 100644 examples/customization/custom-vts-metrics/nginx/default-backend.yaml create mode 100644 examples/customization/custom-vts-metrics/nginx/nginx-ingress-controller.yaml create mode 100644 examples/customization/custom-vts-metrics/nginx/nginx-vts-metrics-conf.yaml diff --git a/examples/customization/custom-vts-metrics/nginx/README.md b/examples/customization/custom-vts-metrics/nginx/README.md new file mode 100644 index 000000000..485a7eadf --- /dev/null +++ b/examples/customization/custom-vts-metrics/nginx/README.md @@ -0,0 +1,74 @@ +# Deploying the Nginx Ingress controller + +This example aims to demonstrate the deployment of an nginx ingress controller and +use a ConfigMap to enable nginx vts module and export metrics for prometheus. + +## Default Backend + +The default backend is a Service capable of handling all url paths and hosts the +nginx controller doesn't understand. This most basic implementation just returns +a 404 page: + +```console +$ kubectl apply -f default-backend.yaml +deployment "default-http-backend" created +service "default-http-backend" created + +$ kubectl -n kube-system get po +NAME READY STATUS RESTARTS AGE +default-http-backend-2657704409-qgwdd 1/1 Running 0 28s +``` + +## Custom configuration + +```console +$ cat nginx-vts-metrics-conf.yaml +apiVersion: v1 +data: + enable-vts-status: "true" +kind: ConfigMap +metadata: + name: nginx-vts-metrics-conf + namespace: kube-system +``` + +```console +$ kubectl create -f nginx-vts-metrics-conf.yaml +``` + +## Custom DH parameters secret + +```console +$> openssl dhparam 1024 2> /dev/null | base64 +LS0tLS1CRUdJTiBESCBQQVJBTUVURVJ... +``` + +```console +$ cat ssl-dh-param.yaml +apiVersion: v1 +data: + dhparam.pem: "LS0tLS1CRUdJTiBESCBQQVJBTUVURVJ..." +kind: Secret +type: Opaque +metadata: + name: lb-dhparam + namespace: kube-system +``` +## Controller + +You can deploy the controller as follows: + +```console +$ kubectl apply -f nginx-ingress-controller.yaml +deployment "nginx-ingress-controller" created + +$ kubectl -n kube-system get po +NAME READY STATUS RESTARTS AGE +default-http-backend-2657704409-qgwdd 1/1 Running 0 2m +nginx-ingress-controller-873061567-4n3k2 1/1 Running 0 42s +``` + +## Test + +Check the contents of the configmap is present in the nginx.conf file using: +`kubectl exec nginx-ingress-controller-873061567-4n3k2 -n kube-system cat /etc/nginx/nginx.conf` diff --git a/examples/customization/custom-vts-metrics/nginx/default-backend.yaml b/examples/customization/custom-vts-metrics/nginx/default-backend.yaml new file mode 100644 index 000000000..3c40989a3 --- /dev/null +++ b/examples/customization/custom-vts-metrics/nginx/default-backend.yaml @@ -0,0 +1,51 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: default-http-backend + labels: + k8s-app: default-http-backend + namespace: kube-system +spec: + replicas: 1 + template: + metadata: + labels: + k8s-app: default-http-backend + spec: + terminationGracePeriodSeconds: 60 + containers: + - name: default-http-backend + # Any image is permissable as long as: + # 1. It serves a 404 page at / + # 2. It serves 200 on a /healthz endpoint + image: gcr.io/google_containers/defaultbackend:1.0 + livenessProbe: + httpGet: + path: /healthz + port: 8080 + scheme: HTTP + initialDelaySeconds: 30 + timeoutSeconds: 5 + ports: + - containerPort: 8080 + resources: + limits: + cpu: 10m + memory: 20Mi + requests: + cpu: 10m + memory: 20Mi +--- +apiVersion: v1 +kind: Service +metadata: + name: default-http-backend + namespace: kube-system + labels: + k8s-app: default-http-backend +spec: + ports: + - port: 80 + targetPort: 8080 + selector: + k8s-app: default-http-backend diff --git a/examples/customization/custom-vts-metrics/nginx/nginx-ingress-controller.yaml b/examples/customization/custom-vts-metrics/nginx/nginx-ingress-controller.yaml new file mode 100644 index 000000000..55c6ec4fd --- /dev/null +++ b/examples/customization/custom-vts-metrics/nginx/nginx-ingress-controller.yaml @@ -0,0 +1,56 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: nginx-ingress-controller + labels: + k8s-app: nginx-ingress-controller + namespace: kube-system + annotations: + prometheus.io/port: "10254" + prometheus.io/scrape: "true" +spec: + replicas: 1 + template: + metadata: + labels: + k8s-app: nginx-ingress-controller + spec: + # hostNetwork makes it possible to use ipv6 and to preserve the source IP correctly regardless of docker configuration + # however, it is not a hard dependency of the nginx-ingress-controller itself and it may cause issues if port 10254 already is taken on the host + # that said, since hostPort is broken on CNI (https://github.com/kubernetes/kubernetes/issues/31307) we have to use hostNetwork where CNI is used + # like with kubeadm + # hostNetwork: true + terminationGracePeriodSeconds: 60 + containers: + - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.3 + name: nginx-ingress-controller + readinessProbe: + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + livenessProbe: + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + timeoutSeconds: 1 + ports: + - containerPort: 80 + hostPort: 80 + - containerPort: 443 + hostPort: 443 + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + args: + - /nginx-ingress-controller + - --default-backend-service=$(POD_NAMESPACE)/default-http-backend + - --configmap=$(POD_NAMESPACE)/nginx-vts-metrics-conf diff --git a/examples/customization/custom-vts-metrics/nginx/nginx-vts-metrics-conf.yaml b/examples/customization/custom-vts-metrics/nginx/nginx-vts-metrics-conf.yaml new file mode 100644 index 000000000..345f19a9a --- /dev/null +++ b/examples/customization/custom-vts-metrics/nginx/nginx-vts-metrics-conf.yaml @@ -0,0 +1,7 @@ +piVersion: v1 +data: + enable-vts-status: "true" +kind: ConfigMap +metadata: + name: nginx-vts-metrics-conf + namespace: kube-system From be05d403ac473545fdfdaf656bc2f7ae856fb159 Mon Sep 17 00:00:00 2001 From: zoues Date: Tue, 21 Mar 2017 23:35:43 +0800 Subject: [PATCH 28/35] fix vts readme --- .../custom-vts-metrics/nginx/README.md | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/examples/customization/custom-vts-metrics/nginx/README.md b/examples/customization/custom-vts-metrics/nginx/README.md index 485a7eadf..df2c4c68b 100644 --- a/examples/customization/custom-vts-metrics/nginx/README.md +++ b/examples/customization/custom-vts-metrics/nginx/README.md @@ -36,24 +36,6 @@ metadata: $ kubectl create -f nginx-vts-metrics-conf.yaml ``` -## Custom DH parameters secret - -```console -$> openssl dhparam 1024 2> /dev/null | base64 -LS0tLS1CRUdJTiBESCBQQVJBTUVURVJ... -``` - -```console -$ cat ssl-dh-param.yaml -apiVersion: v1 -data: - dhparam.pem: "LS0tLS1CRUdJTiBESCBQQVJBTUVURVJ..." -kind: Secret -type: Opaque -metadata: - name: lb-dhparam - namespace: kube-system -``` ## Controller You can deploy the controller as follows: @@ -68,7 +50,7 @@ default-http-backend-2657704409-qgwdd 1/1 Running 0 2m nginx-ingress-controller-873061567-4n3k2 1/1 Running 0 42s ``` -## Test +## Result Check the contents of the configmap is present in the nginx.conf file using: -`kubectl exec nginx-ingress-controller-873061567-4n3k2 -n kube-system cat /etc/nginx/nginx.conf` +`kubectl exec nginx-ingress-controller-873061567-4n3k2 -n kube-system curl localhost:10254/metrics` From 5446208d5fbfaabaa0641d99b349fa144fa2ec1b Mon Sep 17 00:00:00 2001 From: zoues Date: Wed, 22 Mar 2017 09:38:21 +0800 Subject: [PATCH 29/35] Update README.md --- .../customization/custom-vts-metrics/nginx/README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/customization/custom-vts-metrics/nginx/README.md b/examples/customization/custom-vts-metrics/nginx/README.md index df2c4c68b..ca65f3025 100644 --- a/examples/customization/custom-vts-metrics/nginx/README.md +++ b/examples/customization/custom-vts-metrics/nginx/README.md @@ -51,6 +51,9 @@ nginx-ingress-controller-873061567-4n3k2 1/1 Running 0 42s ``` ## Result - -Check the contents of the configmap is present in the nginx.conf file using: -`kubectl exec nginx-ingress-controller-873061567-4n3k2 -n kube-system curl localhost:10254/metrics` +Check wether to open the vts status: +```console +$ kubectl exec nginx-ingress-controller-873061567-4n3k2 -n kube-system cat /etc/nginx/nginx.conf|grep vhost_traffic_status_display + vhost_traffic_status_display; + vhost_traffic_status_display_format html; +``` From 04b87d59453273edeeb05f8f6289c39c0aeb8c73 Mon Sep 17 00:00:00 2001 From: Matthew Sachs Date: Wed, 22 Mar 2017 00:18:26 -0700 Subject: [PATCH 30/35] Add 35.191.0.0/16 range to GCE firewalls (issue #478) --- controllers/gce/README.md | 4 ++-- controllers/gce/firewalls/firewalls.go | 20 ++++++++++---------- docs/faq/gce.md | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/controllers/gce/README.md b/controllers/gce/README.md index 1dbf3b0e4..aa9684344 100644 --- a/controllers/gce/README.md +++ b/controllers/gce/README.md @@ -649,12 +649,12 @@ If you hit that it means the controller isn't even starting. Re-check your input A default GKE/GCE cluster needs at least 1 firewall rule for GLBC to function. The Ingress controller should create this for you automatically. You can also create it thus: ```console $ gcloud compute firewall-rules create allow-130-211-0-0-22 \ - --source-ranges 130.211.0.0/22 \ + --source-ranges 130.211.0.0/22,35.191.0.0/16 \ --target-tags $TAG \ --allow tcp:$NODE_PORT ``` -Where `130.211.0.0/22` is the source range of the GCE L7, `$NODE_PORT` is the node port your Service is exposed on, i.e: +Where `130.211.0.0/22` and `35.191.0.0/16` are the source ranges of the GCE L7, `$NODE_PORT` is the node port your Service is exposed on, i.e: ```console $ kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services ${SERVICE_NAME} ``` diff --git a/controllers/gce/firewalls/firewalls.go b/controllers/gce/firewalls/firewalls.go index 31bfdacf1..7a4d6603c 100644 --- a/controllers/gce/firewalls/firewalls.go +++ b/controllers/gce/firewalls/firewalls.go @@ -26,25 +26,25 @@ import ( "k8s.io/kubernetes/pkg/util/sets" ) -// Src range from which the GCE L7 performs health checks. -const l7SrcRange = "130.211.0.0/22" +// Src ranges from which the GCE L7 performs health checks. +var l7SrcRanges = []string{"130.211.0.0/22", "35.191.0.0/16"} // FirewallRules manages firewall rules. type FirewallRules struct { - cloud Firewall - namer *utils.Namer - srcRange netset.IPNet + cloud Firewall + namer *utils.Namer + srcRanges netset.IPNet } // NewFirewallPool creates a new firewall rule manager. // cloud: the cloud object implementing Firewall. // namer: cluster namer. func NewFirewallPool(cloud Firewall, namer *utils.Namer) SingleFirewallPool { - srcNetSet, err := netset.ParseIPNets(l7SrcRange) + srcNetSet, err := netset.ParseIPNets(l7SrcRanges...) if err != nil { - glog.Fatalf("Could not parse L7 src range %v for firewall rule: %v", l7SrcRange, err) + glog.Fatalf("Could not parse L7 src ranges %v for firewall rule: %v", l7SrcRanges, err) } - return &FirewallRules{cloud: cloud, namer: namer, srcRange: srcNetSet} + return &FirewallRules{cloud: cloud, namer: namer, srcRanges: srcNetSet} } // Sync sync firewall rules with the cloud. @@ -60,7 +60,7 @@ func (fr *FirewallRules) Sync(nodePorts []int64, nodeNames []string) error { rule, _ := fr.cloud.GetFirewall(name) if rule == nil { glog.Infof("Creating global l7 firewall rule %v", name) - return fr.cloud.CreateFirewall(suffix, "GCE L7 firewall rule", fr.srcRange, nodePorts, nodeNames) + return fr.cloud.CreateFirewall(suffix, "GCE L7 firewall rule", fr.srcRanges, nodePorts, nodeNames) } requiredPorts := sets.NewString() @@ -77,7 +77,7 @@ func (fr *FirewallRules) Sync(nodePorts []int64, nodeNames []string) error { return nil } glog.V(3).Infof("Firewall rule %v already exists, updating nodeports %v", name, nodePorts) - return fr.cloud.UpdateFirewall(suffix, "GCE L7 firewall rule", fr.srcRange, nodePorts, nodeNames) + return fr.cloud.UpdateFirewall(suffix, "GCE L7 firewall rule", fr.srcRanges, nodePorts, nodeNames) } // Shutdown shuts down this firewall rules manager. diff --git a/docs/faq/gce.md b/docs/faq/gce.md index f42afd15d..f8fd5fe73 100644 --- a/docs/faq/gce.md +++ b/docs/faq/gce.md @@ -72,7 +72,7 @@ In addition to this pipeline: Service * Each port on the Backend Service has a matching port on the Instance Group * Each port on the Backend Service is exposed through a firewall-rule open - to the GCE LB IP range (`130.211.0.0/22`) + to the GCE LB IP ranges (`130.211.0.0/22` and `35.191.0.0/16`) ## The Ingress controller events complain about quota, how do I increase it? From 3b55e09e23162f6d4da64a9367fb6026329a4c66 Mon Sep 17 00:00:00 2001 From: Thomas Peitz Date: Wed, 22 Mar 2017 15:48:15 +0100 Subject: [PATCH 31/35] Remove unnecessary quote in nginx log format --- controllers/nginx/pkg/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/nginx/pkg/config/config.go b/controllers/nginx/pkg/config/config.go index ffd54676a..15fa300d3 100644 --- a/controllers/nginx/pkg/config/config.go +++ b/controllers/nginx/pkg/config/config.go @@ -47,7 +47,7 @@ const ( gzipTypes = "application/atom+xml application/javascript application/x-javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component" - logFormatUpstream = `%v - [$proxy_add_x_forwarded_for] - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status"` + logFormatUpstream = `%v - [$proxy_add_x_forwarded_for] - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status` logFormatStream = `[$time_local] $protocol [$ssl_preread_server_name] [$stream_upstream] $status $bytes_sent $bytes_received $session_time` From 031fdfd730389d95be170eacbf29afa97e678c35 Mon Sep 17 00:00:00 2001 From: mrmm Date: Wed, 22 Mar 2017 15:12:52 +0000 Subject: [PATCH 32/35] Fix typo nginx configMap vts metrics customization --- .../custom-vts-metrics/nginx/nginx-vts-metrics-conf.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/customization/custom-vts-metrics/nginx/nginx-vts-metrics-conf.yaml b/examples/customization/custom-vts-metrics/nginx/nginx-vts-metrics-conf.yaml index 345f19a9a..28c82955c 100644 --- a/examples/customization/custom-vts-metrics/nginx/nginx-vts-metrics-conf.yaml +++ b/examples/customization/custom-vts-metrics/nginx/nginx-vts-metrics-conf.yaml @@ -1,4 +1,4 @@ -piVersion: v1 +apiVersion: v1 data: enable-vts-status: "true" kind: ConfigMap From a94d31e87db7c8e71f3e788575a39c95bf463766 Mon Sep 17 00:00:00 2001 From: Nick Sardo Date: Tue, 21 Mar 2017 17:05:17 -0700 Subject: [PATCH 33/35] glbc: watch backend service --- controllers/gce/controller/utils.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/controllers/gce/controller/utils.go b/controllers/gce/controller/utils.go index 7efc6cd56..ef8241578 100644 --- a/controllers/gce/controller/utils.go +++ b/controllers/gce/controller/utils.go @@ -216,18 +216,29 @@ func (s *StoreToIngressLister) List() (ing extensions.IngressList, err error) { // GetServiceIngress gets all the Ingress' that have rules pointing to a service. // Note that this ignores services without the right nodePorts. func (s *StoreToIngressLister) GetServiceIngress(svc *api.Service) (ings []extensions.Ingress, err error) { +IngressLoop: for _, m := range s.Store.List() { ing := *m.(*extensions.Ingress) if ing.Namespace != svc.Namespace { continue } - for _, rules := range ing.Spec.Rules { - if rules.IngressRuleValue.HTTP == nil { + + // Check service of default backend + if ing.Spec.Backend != nil && ing.Spec.Backend.ServiceName == svc.Name { + ings = append(ings, ing) + continue + } + + // Check the target service for each path rule + for _, rule := range ing.Spec.Rules { + if rule.IngressRuleValue.HTTP == nil { continue } - for _, p := range rules.IngressRuleValue.HTTP.Paths { + for _, p := range rule.IngressRuleValue.HTTP.Paths { if p.Backend.ServiceName == svc.Name { ings = append(ings, ing) + // Skip the rest of the rules to avoid duplicate ingresses in list + continue IngressLoop } } } From 9f5ed978b98e784cb94468677b90efcbe56ff34b Mon Sep 17 00:00:00 2001 From: chentao1596 Date: Fri, 24 Mar 2017 10:17:39 +0800 Subject: [PATCH 34/35] use interface instead of implementation --- core/pkg/ingress/controller/controller.go | 2 +- core/pkg/ingress/controller/named_port.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/pkg/ingress/controller/controller.go b/core/pkg/ingress/controller/controller.go index 036e38d50..a2ca86bd1 100644 --- a/core/pkg/ingress/controller/controller.go +++ b/core/pkg/ingress/controller/controller.go @@ -111,7 +111,7 @@ type GenericController struct { // Configuration contains all the settings required by an Ingress controller type Configuration struct { - Client *clientset.Clientset + Client clientset.Interface ResyncPeriod time.Duration DefaultService string diff --git a/core/pkg/ingress/controller/named_port.go b/core/pkg/ingress/controller/named_port.go index abc1e6ef2..da28df135 100644 --- a/core/pkg/ingress/controller/named_port.go +++ b/core/pkg/ingress/controller/named_port.go @@ -38,7 +38,7 @@ import ( func (ic *GenericController) checkSvcForUpdate(svc *api.Service) error { // get the pods associated with the service // TODO: switch this to a watch - pods, err := ic.cfg.Client.Pods(svc.Namespace).List(api.ListOptions{ + pods, err := ic.cfg.Client.Core().Pods(svc.Namespace).List(api.ListOptions{ LabelSelector: labels.Set(svc.Spec.Selector).AsSelector(), }) @@ -82,7 +82,7 @@ func (ic *GenericController) checkSvcForUpdate(svc *api.Service) error { if len(namedPorts) > 0 && !reflect.DeepEqual(curNamedPort, namedPorts) { data, _ := json.Marshal(namedPorts) - newSvc, err := ic.cfg.Client.Services(svc.Namespace).Get(svc.Name) + newSvc, err := ic.cfg.Client.Core().Services(svc.Namespace).Get(svc.Name) if err != nil { return fmt.Errorf("error getting service %v/%v: %v", svc.Namespace, svc.Name, err) } @@ -93,7 +93,7 @@ func (ic *GenericController) checkSvcForUpdate(svc *api.Service) error { newSvc.ObjectMeta.Annotations[service.NamedPortAnnotation] = string(data) glog.Infof("updating service %v with new named port mappings", svc.Name) - _, err = ic.cfg.Client.Services(svc.Namespace).Update(newSvc) + _, err = ic.cfg.Client.Core().Services(svc.Namespace).Update(newSvc) if err != nil { return fmt.Errorf("error syncing service %v/%v: %v", svc.Namespace, svc.Name, err) } From 740f7caeb838f3f8e532a2fa4d7dfdb02f2719b2 Mon Sep 17 00:00:00 2001 From: chentao1596 Date: Fri, 24 Mar 2017 11:02:10 +0800 Subject: [PATCH 35/35] add unit test case for named_port --- .../pkg/ingress/controller/named_port_test.go | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 core/pkg/ingress/controller/named_port_test.go diff --git a/core/pkg/ingress/controller/named_port_test.go b/core/pkg/ingress/controller/named_port_test.go new file mode 100644 index 000000000..c92ad9806 --- /dev/null +++ b/core/pkg/ingress/controller/named_port_test.go @@ -0,0 +1,191 @@ +/* +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 controller + +import ( + "reflect" + "testing" + + "k8s.io/ingress/core/pkg/ingress/annotations/service" + "k8s.io/kubernetes/pkg/api" + testclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" + "k8s.io/kubernetes/pkg/util/intstr" +) + +func buildSimpleClientSet() *testclient.Clientset { + return testclient.NewSimpleClientset( + &api.PodList{Items: []api.Pod{ + { + ObjectMeta: api.ObjectMeta{ + Name: "foo1", + Namespace: api.NamespaceDefault, + Labels: map[string]string{ + "lable_sig": "foo_pod", + }, + }, + Spec: api.PodSpec{ + NodeName: "foo_node_1", + Containers: []api.Container{ + { + Ports: []api.ContainerPort{ + { + Name: "foo1_named_port_c1", + Protocol: api.ProtocolTCP, + ContainerPort: 80, + }, + }, + }, + }, + }, + }, + { + ObjectMeta: api.ObjectMeta{ + Name: "foo1", + Namespace: api.NamespaceSystem, + Labels: map[string]string{ + "lable_sig": "foo_pod", + }, + }, + }, + }}, + &api.ServiceList{Items: []api.Service{ + { + ObjectMeta: api.ObjectMeta{ + Namespace: api.NamespaceDefault, + Name: "named_port_test_service", + }, + }, + }}, + ) +} + +func buildGenericController() *GenericController { + return &GenericController{ + cfg: &Configuration{ + Client: buildSimpleClientSet(), + }, + } +} + +func buildService() *api.Service { + return &api.Service{ + ObjectMeta: api.ObjectMeta{ + Namespace: api.NamespaceSystem, + Name: "named_port_test_service", + }, + + Spec: api.ServiceSpec{ + ClusterIP: "10.10.10.10", + }, + } +} + +func TestCheckSvcForUpdate(t *testing.T) { + foos := []struct { + n string + ns string + sps []api.ServicePort + sl map[string]string + er string + }{ + { + "pods_have_not_been_found_in_this_namespace", + api.NamespaceSystem, + []api.ServicePort{ + {Name: "foo_port_1", Port: 8080, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_c1")}, + {Name: "foo_port_2", Port: 8181, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(81)}, + {Name: "foo_port_3", Port: 8282, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("")}, + }, + map[string]string{ + "lable_sig": "foo_pod", + }, + "", + }, + { + "ports_have_not_been_found_in_this_pod", + api.NamespaceDefault, + []api.ServicePort{ + {Name: "foo_port_1", Port: 8080, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_cXX")}, + {Name: "foo_port_2", Port: 8181, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(81)}, + {Name: "foo_port_3", Port: 8282, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("")}, + }, + map[string]string{ + "lable_sig": "foo_pod", + }, + "", + }, + + { + "ports_fixed", + api.NamespaceDefault, + []api.ServicePort{ + {Name: "foo_port_1", Port: 8080, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(80)}, + {Name: "foo_port_2", Port: 8181, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(81)}, + {Name: "foo_port_3", Port: 8282, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("")}, + }, + map[string]string{ + "lable_sig": "foo_pod", + }, + "", + }, + { + "nil_selector", + api.NamespaceDefault, + []api.ServicePort{ + {Name: "foo_port_1", Port: 8080, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_c1")}, + {Name: "foo_port_2", Port: 8181, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(81)}, + {Name: "foo_port_3", Port: 8282, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("")}, + }, + nil, + "{\"foo1_named_port_c1\":\"80\"}", + }, + { + "normal_update", + api.NamespaceDefault, + []api.ServicePort{ + {Name: "foo_port_1", Port: 8080, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_c1")}, + {Name: "foo_port_2", Port: 8181, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(81)}, + {Name: "foo_port_3", Port: 8282, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("")}, + }, + map[string]string{ + "lable_sig": "foo_pod", + }, + "{\"foo1_named_port_c1\":\"80\"}", + }, + } + + for _, foo := range foos { + t.Run(foo.n, func(t *testing.T) { + gc := buildGenericController() + s := buildService() + s.SetNamespace(foo.ns) + s.Spec.Ports = foo.sps + s.Spec.Selector = foo.sl + + err := gc.checkSvcForUpdate(s) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + rs, _ := gc.cfg.Client.Core().Services(api.NamespaceDefault).Get("named_port_test_service") + rr := rs.ObjectMeta.Annotations[service.NamedPortAnnotation] + if !reflect.DeepEqual(rr, foo.er) { + t.Errorf("Returned %s, but expected %s for %s", rr, foo.er, foo.n) + } + }) + } +}