From 5a67d0ac84767d5e225bb10185511aa7b3c86c6e Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Thu, 8 Dec 2016 13:32:52 +0100 Subject: [PATCH] Fix panic in k8s loadIngresses Signed-off-by: Emile Vauge --- acme/acme.go | 2 +- cluster/datastore.go | 2 +- provider/kubernetes.go | 4 ++++ safe/routine.go | 5 ++--- safe/routine_test.go | 21 +++++++++++++++++++++ 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/acme/acme.go b/acme/acme.go index 64cb21c44..8759b666d 100644 --- a/acme/acme.go +++ b/acme/acme.go @@ -533,7 +533,7 @@ func (a *ACME) LoadCertificateForDomains(domains []string) { } ebo := backoff.NewExponentialBackOff() ebo.MaxElapsedTime = 30 * time.Second - err := backoff.RetryNotify(operation, ebo, notify) + err := backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify) if err != nil { log.Errorf("Error getting ACME client: %v", err) return diff --git a/cluster/datastore.go b/cluster/datastore.go index fe552d897..538d70be5 100644 --- a/cluster/datastore.go +++ b/cluster/datastore.go @@ -177,7 +177,7 @@ func (d *Datastore) Begin() (Transaction, Object, error) { } ebo := backoff.NewExponentialBackOff() ebo.MaxElapsedTime = 60 * time.Second - err = backoff.RetryNotify(operation, ebo, notify) + err = backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify) if err != nil { return nil, nil, fmt.Errorf("Datastore cannot sync: %v", err) } diff --git a/provider/kubernetes.go b/provider/kubernetes.go index cb1c367a2..16c09d2ea 100644 --- a/provider/kubernetes.go +++ b/provider/kubernetes.go @@ -110,6 +110,10 @@ func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configur PassHostHeader := provider.getPassHostHeader() for _, i := range ingresses { for _, r := range i.Spec.Rules { + if r.HTTP == nil { + log.Warnf("Error in ingress: HTTP is nil") + continue + } for _, pa := range r.HTTP.Paths { if _, exists := templateObjects.Backends[r.Host+pa.Path]; !exists { templateObjects.Backends[r.Host+pa.Path] = &types.Backend{ diff --git a/safe/routine.go b/safe/routine.go index 62d666963..4d32f2a55 100644 --- a/safe/routine.go +++ b/safe/routine.go @@ -152,11 +152,10 @@ func OperationWithRecover(operation backoff.Operation) backoff.Operation { return func() (err error) { defer func() { if res := recover(); res != nil { - defaultRecoverGoroutine(err) + defaultRecoverGoroutine(res) err = fmt.Errorf("Panic in operation: %s", err) } }() - err = operation() - return nil + return operation() } } diff --git a/safe/routine_test.go b/safe/routine_test.go index 07fa89193..11bdccf13 100644 --- a/safe/routine_test.go +++ b/safe/routine_test.go @@ -1,11 +1,22 @@ package safe import ( + "fmt" "github.com/cenk/backoff" "testing" ) func TestOperationWithRecover(t *testing.T) { + operation := func() error { + return nil + } + err := backoff.Retry(OperationWithRecover(operation), &backoff.StopBackOff{}) + if err != nil { + t.Fatalf("Error in OperationWithRecover: %s", err) + } +} + +func TestOperationWithRecoverPanic(t *testing.T) { operation := func() error { panic("BOOM") } @@ -14,3 +25,13 @@ func TestOperationWithRecover(t *testing.T) { t.Fatalf("Error in OperationWithRecover: %s", err) } } + +func TestOperationWithRecoverError(t *testing.T) { + operation := func() error { + return fmt.Errorf("ERROR") + } + err := backoff.Retry(OperationWithRecover(operation), &backoff.StopBackOff{}) + if err == nil { + t.Fatalf("Error in OperationWithRecover: %s", err) + } +}