251 lines
4.6 KiB
Go
251 lines
4.6 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"time"
|
|
|
|
"github.com/go-logr/logr/funcr"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
|
|
"github.com/kedacore/http-add-on/pkg/util"
|
|
)
|
|
|
|
var _ = Describe("ProbeHandler", func() {
|
|
Context("New", func() {
|
|
It("returns new object with expected fields", func() {
|
|
var (
|
|
ctx = context.Background()
|
|
ret = errors.New("test error")
|
|
)
|
|
|
|
var b bool
|
|
healthCheckers := []util.HealthChecker{
|
|
util.HealthCheckerFunc(func(_ context.Context) error {
|
|
b = true
|
|
|
|
return ret
|
|
}),
|
|
}
|
|
|
|
ph := NewProbe(healthCheckers)
|
|
Expect(ph).NotTo(BeNil())
|
|
|
|
h := ph.healthy.Load()
|
|
Expect(h).To(BeFalse())
|
|
|
|
hcs := ph.healthCheckers
|
|
Expect(hcs).To(HaveLen(1))
|
|
|
|
hc := hcs[0]
|
|
Expect(hc).NotTo(BeNil())
|
|
|
|
err := hc.HealthCheck(ctx)
|
|
Expect(err).To(MatchError(ret))
|
|
|
|
Expect(b).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
Context("ServeHTTP", func() {
|
|
const (
|
|
host = "keda.sh"
|
|
path = "/README"
|
|
)
|
|
|
|
var (
|
|
w *httptest.ResponseRecorder
|
|
r *http.Request
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
w = httptest.NewRecorder()
|
|
|
|
r = httptest.NewRequest(http.MethodGet, path, nil)
|
|
r.Host = host
|
|
})
|
|
|
|
When("healthy", func() {
|
|
It("serves 200", func() {
|
|
var (
|
|
sc = http.StatusOK
|
|
st = http.StatusText(sc)
|
|
)
|
|
|
|
var ph Probe
|
|
ph.healthy.Store(true)
|
|
|
|
ph.ServeHTTP(w, r)
|
|
|
|
Expect(w.Code).To(Equal(sc))
|
|
Expect(w.Body.String()).To(Equal(st))
|
|
})
|
|
})
|
|
|
|
When("unhealthy", func() {
|
|
It("serves 503", func() {
|
|
var (
|
|
sc = http.StatusServiceUnavailable
|
|
st = http.StatusText(sc)
|
|
)
|
|
|
|
var ph Probe
|
|
ph.healthy.Store(false)
|
|
|
|
ph.ServeHTTP(w, r)
|
|
|
|
Expect(w.Code).To(Equal(sc))
|
|
Expect(w.Body.String()).To(Equal(st))
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("Start", func() {
|
|
It("returns when context is done", func() {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
|
|
var ph Probe
|
|
err := util.WithTimeout(time.Second, func() error {
|
|
ph.Start(ctx)
|
|
|
|
return nil
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("invokes check every second", func() {
|
|
const (
|
|
n = 10
|
|
)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
var i int
|
|
ph := Probe{
|
|
healthCheckers: []util.HealthChecker{
|
|
util.HealthCheckerFunc(func(_ context.Context) error {
|
|
i++
|
|
|
|
return nil
|
|
}),
|
|
},
|
|
}
|
|
|
|
go ph.Start(ctx)
|
|
|
|
time.Sleep(n * time.Second)
|
|
|
|
Expect(i).To(BeNumerically("~", n, 2))
|
|
})
|
|
})
|
|
|
|
Context("check", func() {
|
|
When("all health checks succeed", func() {
|
|
It("sets healthy to true", func() {
|
|
var (
|
|
ctx = context.Background()
|
|
)
|
|
|
|
var bs []bool
|
|
ph := Probe{
|
|
healthCheckers: []util.HealthChecker{
|
|
util.HealthCheckerFunc(func(_ context.Context) error {
|
|
bs = append(bs, true)
|
|
return nil
|
|
}),
|
|
util.HealthCheckerFunc(func(_ context.Context) error {
|
|
bs = append(bs, true)
|
|
return nil
|
|
}),
|
|
util.HealthCheckerFunc(func(_ context.Context) error {
|
|
bs = append(bs, true)
|
|
return nil
|
|
}),
|
|
},
|
|
}
|
|
|
|
ph.check(ctx)
|
|
|
|
healthCheckersLen := len(ph.healthCheckers)
|
|
Expect(bs).To(HaveLen(healthCheckersLen))
|
|
|
|
healthy := ph.healthy.Load()
|
|
Expect(healthy).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
When("a health check fail", func() {
|
|
It("sets healthy to false", func() {
|
|
var (
|
|
ctx = context.Background()
|
|
)
|
|
|
|
ph := Probe{
|
|
healthCheckers: []util.HealthChecker{
|
|
util.HealthCheckerFunc(func(_ context.Context) error {
|
|
return nil
|
|
}),
|
|
util.HealthCheckerFunc(func(_ context.Context) error {
|
|
return context.Canceled
|
|
}),
|
|
util.HealthCheckerFunc(func(_ context.Context) error {
|
|
return nil
|
|
}),
|
|
},
|
|
}
|
|
ph.healthy.Store(true)
|
|
|
|
ph.check(ctx)
|
|
|
|
healthy := ph.healthy.Load()
|
|
Expect(healthy).To(BeFalse())
|
|
})
|
|
|
|
It("logs the returned error", func() {
|
|
const (
|
|
msg = "health check function failed"
|
|
)
|
|
|
|
var (
|
|
ctx = context.Background()
|
|
ret = errors.New("test error")
|
|
)
|
|
|
|
var b bool
|
|
ctx = util.ContextWithLogger(ctx, funcr.NewJSON(
|
|
func(obj string) {
|
|
var m map[string]interface{}
|
|
|
|
err := json.Unmarshal([]byte(obj), &m)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(m).To(HaveKeyWithValue("msg", msg))
|
|
Expect(m).To(HaveKeyWithValue("error", ret.Error()))
|
|
|
|
b = true
|
|
},
|
|
funcr.Options{},
|
|
))
|
|
|
|
ph := Probe{
|
|
healthCheckers: []util.HealthChecker{
|
|
util.HealthCheckerFunc(func(_ context.Context) error {
|
|
return ret
|
|
}),
|
|
},
|
|
}
|
|
|
|
ph.check(ctx)
|
|
|
|
Expect(b).To(BeTrue())
|
|
})
|
|
})
|
|
})
|
|
})
|