From 827fcf10ddc6b5c648d38c3450477c21280a13ce Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Thu, 10 Nov 2016 22:45:20 -0300 Subject: [PATCH] Fix lint errors --- .travis.yml | 4 +- Makefile | 69 ++++++++ README.adoc | 2 +- controllers/gce/controller/controller.go | 2 +- controllers/gce/controller/controller_test.go | 4 +- controllers/gce/controller/utils.go | 4 +- controllers/gce/storage/configmaps.go | 14 +- core/pkg/ingress/controller/backend_ssl.go | 161 ++++++++++++++++++ 8 files changed, 246 insertions(+), 14 deletions(-) create mode 100644 Makefile create mode 100644 core/pkg/ingress/controller/backend_ssl.go diff --git a/.travis.yml b/.travis.yml index 23b4e3276..a55e7c8c7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,8 @@ before_script: - export PATH=$PATH:$PWD/hack/e2e-internal/ script: - - make fmt lint vet cover + # enable kubernetes/ingress in + # coveralls.io and add cover task + - make fmt lint vet test - make controllers controllers-images #- make test-e2e diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..966831460 --- /dev/null +++ b/Makefile @@ -0,0 +1,69 @@ +all: push + +BUILDTAGS= + +# building inside travis generates a custom version of the +# backends in order to run e2e tests agains the build. +ifdef TRAVIS_BUILD_ID + RELEASE := ci-build-${TRAVIS_BUILD_ID} +endif + +# 0.0 shouldn't clobber any release builds +RELEASE?=0.0 + +# by default build a linux version +GOOS?=linux + +REPO_INFO=$(shell git config --get remote.origin.url) + +ifndef COMMIT + COMMIT := git-$(shell git rev-parse --short HEAD) +endif + +# base package. It contains the common and backends code +PKG := "k8s.io/ingress" + +# TODO: fix lint errors in gce controller +GO_LIST_FILES=$(shell go list ${PKG}/... | grep -v vendor | grep -v -e "test/e2e" -e "controllers/gce/loadbalancers" -e "controllers/gce/controller") + +.PHONY: fmt +fmt: + @go list -f '{{if len .TestGoFiles}}"gofmt -s -l {{.Dir}}"{{end}}' ${GO_LIST_FILES} | xargs -L 1 sh -c + +.PHONY: lint +lint: + @go list -f '{{if len .TestGoFiles}}"golint {{.Dir}}/..."{{end}}' ${GO_LIST_FILES} | xargs -L 1 sh -c + +.PHONY: test +test: + @go test -v -race -tags "$(BUILDTAGS) cgo" ${GO_LIST_FILES} + +.PHONY: test-e2e +test-e2e: ginkgo + @go run hack/e2e.go -v --up --test --down + +.PHONY: cover +cover: + @go list -f '{{if len .TestGoFiles}}"go test -coverprofile={{.Dir}}/.coverprofile {{.ImportPath}}"{{end}}' ${GO_LIST_FILES} | xargs -L 1 sh -c + gover + goveralls -coverprofile=gover.coverprofile -service travis-ci -repotoken ${COVERALLS_TOKEN} + +.PHONY: vet +vet: + @go vet ${GO_LIST_FILES} + +.PHONY: clean +clean: + make -C controllers/nginx clean + +.PHONY: controllers +controllers: + make -C controllers/nginx build + +.PHONY: controllers-images +controllers-images: + make -C controllers/nginx container + +.PHONY: ginkgo +ginkgo: + go get github.com/onsi/ginkgo/ginkgo diff --git a/README.adoc b/README.adoc index 74389f58a..9ab9c11c0 100644 --- a/README.adoc +++ b/README.adoc @@ -1,6 +1,6 @@ // vim: ft=asciidoc -[![Build Status](https://travis-ci.org/kubernetes/ingress.svg?branch=master)](https://travis-ci.org/kubernetes/ingress) +image:https://travis-ci.org/kubernetes/ingress.svg?branch=master["Build Status", link="https://travis-ci.org/kubernetes/ingress"] = Ingress :toc: macro diff --git a/controllers/gce/controller/controller.go b/controllers/gce/controller/controller.go index 962ffa292..eb514fd28 100644 --- a/controllers/gce/controller/controller.go +++ b/controllers/gce/controller/controller.go @@ -354,7 +354,7 @@ func (lbc *LoadBalancerController) sync(key string) (err error) { } ing := *obj.(*extensions.Ingress) - if urlMap, err := lbc.tr.toUrlMap(&ing); err != nil { + if urlMap, err := lbc.tr.toURLMap(&ing); err != nil { syncError = fmt.Errorf("%v, convert to url map error %v", syncError, err) } else if err := l7.UpdateUrlMap(urlMap); err != nil { lbc.recorder.Eventf(&ing, api.EventTypeWarning, "UrlMap", err.Error()) diff --git a/controllers/gce/controller/controller_test.go b/controllers/gce/controller/controller_test.go index e26b57fb2..cc58e94b5 100644 --- a/controllers/gce/controller/controller_test.go +++ b/controllers/gce/controller/controller_test.go @@ -51,8 +51,8 @@ func defaultBackendName(clusterName string) string { } // newLoadBalancerController create a loadbalancer controller. -func newLoadBalancerController(t *testing.T, cm *fakeClusterManager, masterUrl string) *LoadBalancerController { - client := client.NewForConfigOrDie(&restclient.Config{Host: masterUrl, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) +func newLoadBalancerController(t *testing.T, cm *fakeClusterManager, masterURL string) *LoadBalancerController { + client := client.NewForConfigOrDie(&restclient.Config{Host: masterURL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) lb, err := NewLoadBalancerController(client, cm.ClusterManager, 1*time.Second, api.NamespaceAll) if err != nil { t.Fatalf("%v", err) diff --git a/controllers/gce/controller/utils.go b/controllers/gce/controller/utils.go index 028e2a6ca..e373205b3 100644 --- a/controllers/gce/controller/utils.go +++ b/controllers/gce/controller/utils.go @@ -226,8 +226,8 @@ type GCETranslator struct { *LoadBalancerController } -// toUrlMap converts an ingress to a map of subdomain: url-regex: gce backend. -func (t *GCETranslator) toUrlMap(ing *extensions.Ingress) (utils.GCEURLMap, error) { +// toURLMap converts an ingress to a map of subdomain: url-regex: gce backend. +func (t *GCETranslator) toURLMap(ing *extensions.Ingress) (utils.GCEURLMap, error) { hostPathBackend := utils.GCEURLMap{} for _, rule := range ing.Spec.Rules { if rule.HTTP == nil { diff --git a/controllers/gce/storage/configmaps.go b/controllers/gce/storage/configmaps.go index 20ac3fd3e..cfed347fc 100644 --- a/controllers/gce/storage/configmaps.go +++ b/controllers/gce/storage/configmaps.go @@ -123,37 +123,37 @@ type ConfigMapStore interface { cache.Store } -// ApiServerConfigMapStore only services Add and GetByKey from apiserver. +// APIServerConfigMapStore only services Add and GetByKey from apiserver. // TODO: Implement all the other store methods and make this a write // through cache. -type ApiServerConfigMapStore struct { +type APIServerConfigMapStore struct { ConfigMapStore client client.Interface } // Add adds the given config map to the apiserver's store. -func (a *ApiServerConfigMapStore) Add(obj interface{}) error { +func (a *APIServerConfigMapStore) Add(obj interface{}) error { cfg := obj.(*api.ConfigMap) _, err := a.client.Core().ConfigMaps(cfg.Namespace).Create(cfg) return err } // Update updates the existing config map object. -func (a *ApiServerConfigMapStore) Update(obj interface{}) error { +func (a *APIServerConfigMapStore) Update(obj interface{}) error { cfg := obj.(*api.ConfigMap) _, err := a.client.Core().ConfigMaps(cfg.Namespace).Update(cfg) return err } // Delete deletes the existing config map object. -func (a *ApiServerConfigMapStore) Delete(obj interface{}) error { +func (a *APIServerConfigMapStore) Delete(obj interface{}) error { cfg := obj.(*api.ConfigMap) return a.client.Core().ConfigMaps(cfg.Namespace).Delete(cfg.Name, &api.DeleteOptions{}) } // GetByKey returns the config map for a given key. // The key must take the form namespace/name. -func (a *ApiServerConfigMapStore) GetByKey(key string) (item interface{}, exists bool, err 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) @@ -173,5 +173,5 @@ func (a *ApiServerConfigMapStore) GetByKey(key string) (item interface{}, exists // NewConfigMapStore returns a config map store capable of persisting updates // to apiserver. func NewConfigMapStore(c client.Interface) ConfigMapStore { - return &ApiServerConfigMapStore{ConfigMapStore: cache.NewStore(cache.MetaNamespaceKeyFunc), client: c} + return &APIServerConfigMapStore{ConfigMapStore: cache.NewStore(cache.MetaNamespaceKeyFunc), client: c} } diff --git a/core/pkg/ingress/controller/backend_ssl.go b/core/pkg/ingress/controller/backend_ssl.go new file mode 100644 index 000000000..eea053913 --- /dev/null +++ b/core/pkg/ingress/controller/backend_ssl.go @@ -0,0 +1,161 @@ +/* +Copyright 2015 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 ( + "fmt" + "strings" + "time" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/client/cache" + + "github.com/golang/glog" + "k8s.io/ingress/core/pkg/ingress" + "k8s.io/ingress/core/pkg/ingress/annotations/parser" + ssl "k8s.io/ingress/core/pkg/net/ssl" +) + +// syncSecret keeps in sync Secrets used by Ingress rules with files to allow +// being used in controllers. +func (ic *GenericController) syncSecret(k interface{}) error { + if ic.secretQueue.IsShuttingDown() { + return nil + } + if !ic.controllersInSync() { + time.Sleep(podStoreSyncedPollPeriod) + return fmt.Errorf("deferring sync till endpoints controller has synced") + } + + // check if the default certificate is configured + key := fmt.Sprintf("default/%v", defServerName) + _, exists := ic.sslCertTracker.Get(key) + var cert *ingress.SSLCert + var err error + if !exists { + if ic.cfg.DefaultSSLCertificate != "" { + cert, err = ic.getPemCertificate(ic.cfg.DefaultSSLCertificate) + if err != nil { + return err + } + } else { + defCert, defKey := ssl.GetFakeSSLCert() + cert, err = ssl.AddOrUpdateCertAndKey("system-snake-oil-certificate", defCert, defKey, []byte{}) + if err != nil { + return nil + } + } + cert.Name = defServerName + cert.Namespace = api.NamespaceDefault + ic.sslCertTracker.Add(key, cert) + } + + key = k.(string) + + // get secret + secObj, exists, err := ic.secrLister.Store.GetByKey(key) + if err != nil { + return fmt.Errorf("error getting secret %v: %v", key, err) + } + if !exists { + return fmt.Errorf("secret %v was not found", key) + } + sec := secObj.(*api.Secret) + if !ic.secrReferenced(sec.Name, sec.Namespace) { + glog.V(2).Infof("secret %v/%v is not used in Ingress rules. skipping ", sec.Namespace, sec.Name) + return nil + } + + cert, err = ic.getPemCertificate(key) + if err != nil { + return err + } + + // create certificates and add or update the item in the store + _, exists = ic.sslCertTracker.Get(key) + if exists { + ic.sslCertTracker.Update(key, cert) + return nil + } + ic.sslCertTracker.Add(key, cert) + return nil +} + +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) + } + if !exists { + return nil, fmt.Errorf("secret named %v does not exists", secretName) + } + + secret := secretInterface.(*api.Secret) + cert, ok := secret.Data[api.TLSCertKey] + if !ok { + return nil, fmt.Errorf("secret named %v has no private key", secretName) + } + key, ok := secret.Data[api.TLSPrivateKeyKey] + if !ok { + return nil, fmt.Errorf("secret named %v has no cert", secretName) + } + + ca := secret.Data["ca.crt"] + + nsSecName := strings.Replace(secretName, "/", "-", -1) + s, err := ssl.AddOrUpdateCertAndKey(nsSecName, cert, key, ca) + if err != nil { + return nil, err + } + + s.Name = secret.Name + s.Namespace = secret.Namespace + return s, nil +} + +// check if secret is referenced in this controller's config +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 ing.Namespace != namespace { + continue + } + for _, tls := range ing.Spec.TLS { + if tls.SecretName == name { + return true + } + } + } + return false +} + +// sslCertTracker ... +type sslCertTracker struct { + cache.ThreadSafeStore +} + +func newSSLCertTracker() *sslCertTracker { + return &sslCertTracker{ + cache.NewThreadSafeStore(cache.Indexers{}, cache.Indices{}), + } +}