From f5bfe681c260beff51b739ebbc13b01bcfdfbfbd 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 55bb09241..12a676854 100644 --- a/acme/acme.go +++ b/acme/acme.go @@ -474,7 +474,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 042b1cd44..db6e87158 100644 --- a/cluster/datastore.go +++ b/cluster/datastore.go @@ -176,7 +176,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 792204563..286905150 100644 --- a/provider/kubernetes.go +++ b/provider/kubernetes.go @@ -196,6 +196,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 292d52bcc..8f719fea4 100644 --- a/safe/routine.go +++ b/safe/routine.go @@ -142,11 +142,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) + } +}