grafana/pkg/api/health_test.go
2023-09-22 08:17:10 -03:00

190 lines
4.3 KiB
Go

package api
import (
"errors"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/db/dbtest"
"github.com/grafana/grafana/pkg/infra/localcache"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
)
func TestHealthAPI_Version(t *testing.T) {
m, _ := setupHealthAPITestEnvironment(t, func(cfg *setting.Cfg) {
cfg.BuildVersion = "7.4.0"
cfg.BuildCommit = "59906ab1bf"
})
req := httptest.NewRequest(http.MethodGet, "/api/health", nil)
rec := httptest.NewRecorder()
m.ServeHTTP(rec, req)
require.Equal(t, 200, rec.Code)
expectedBody := `
{
"database": "ok",
"version": "7.4.0",
"commit": "59906ab1bf"
}
`
require.JSONEq(t, expectedBody, rec.Body.String())
}
func TestHealthAPI_VersionEnterprise(t *testing.T) {
m, _ := setupHealthAPITestEnvironment(t, func(cfg *setting.Cfg) {
cfg.BuildVersion = "7.4.0"
cfg.EnterpriseBuildCommit = "22206ab1be"
cfg.BuildCommit = "59906ab1bf"
})
req := httptest.NewRequest(http.MethodGet, "/api/health", nil)
rec := httptest.NewRecorder()
m.ServeHTTP(rec, req)
require.Equal(t, 200, rec.Code)
expectedBody := `
{
"database": "ok",
"enterpriseCommit": "22206ab1be",
"version": "7.4.0",
"commit": "59906ab1bf"
}
`
require.JSONEq(t, expectedBody, rec.Body.String())
}
func TestHealthAPI_AnonymousHideVersion(t *testing.T) {
m, hs := setupHealthAPITestEnvironment(t)
hs.Cfg.AnonymousHideVersion = true
req := httptest.NewRequest(http.MethodGet, "/api/health", nil)
rec := httptest.NewRecorder()
m.ServeHTTP(rec, req)
require.Equal(t, 200, rec.Code)
expectedBody := `
{
"database": "ok"
}
`
require.JSONEq(t, expectedBody, rec.Body.String())
}
func TestHealthAPI_DatabaseHealthy(t *testing.T) {
const cacheKey = "db-healthy"
m, hs := setupHealthAPITestEnvironment(t)
hs.Cfg.AnonymousHideVersion = true
healthy, found := hs.CacheService.Get(cacheKey)
require.False(t, found)
require.Nil(t, healthy)
req := httptest.NewRequest(http.MethodGet, "/api/health", nil)
rec := httptest.NewRecorder()
m.ServeHTTP(rec, req)
require.Equal(t, 200, rec.Code)
expectedBody := `
{
"database": "ok"
}
`
require.JSONEq(t, expectedBody, rec.Body.String())
healthy, found = hs.CacheService.Get(cacheKey)
require.True(t, found)
require.True(t, healthy.(bool))
}
func TestHealthAPI_DatabaseUnhealthy(t *testing.T) {
const cacheKey = "db-healthy"
m, hs := setupHealthAPITestEnvironment(t)
hs.Cfg.AnonymousHideVersion = true
hs.SQLStore.(*dbtest.FakeDB).ExpectedError = errors.New("bad")
healthy, found := hs.CacheService.Get(cacheKey)
require.False(t, found)
require.Nil(t, healthy)
req := httptest.NewRequest(http.MethodGet, "/api/health", nil)
rec := httptest.NewRecorder()
m.ServeHTTP(rec, req)
require.Equal(t, 503, rec.Code)
expectedBody := `
{
"database": "failing"
}
`
require.JSONEq(t, expectedBody, rec.Body.String())
healthy, found = hs.CacheService.Get(cacheKey)
require.True(t, found)
require.False(t, healthy.(bool))
}
func TestHealthAPI_DatabaseHealthCached(t *testing.T) {
const cacheKey = "db-healthy"
m, hs := setupHealthAPITestEnvironment(t)
hs.Cfg.AnonymousHideVersion = true
// Mock unhealthy database in cache.
hs.CacheService.Set(cacheKey, false, 5*time.Minute)
req := httptest.NewRequest(http.MethodGet, "/api/health", nil)
rec := httptest.NewRecorder()
m.ServeHTTP(rec, req)
require.Equal(t, 503, rec.Code)
expectedBody := `
{
"database": "failing"
}
`
require.JSONEq(t, expectedBody, rec.Body.String())
// Purge cache and redo request.
hs.CacheService.Delete(cacheKey)
rec = httptest.NewRecorder()
m.ServeHTTP(rec, req)
require.Equal(t, 200, rec.Code)
expectedBody = `
{
"database": "ok"
}
`
require.JSONEq(t, expectedBody, rec.Body.String())
healthy, found := hs.CacheService.Get(cacheKey)
require.True(t, found)
require.True(t, healthy.(bool))
}
func setupHealthAPITestEnvironment(t *testing.T, cbs ...func(*setting.Cfg)) (*web.Mux, *HTTPServer) {
t.Helper()
m := web.New()
cfg := setting.NewCfg()
for _, cb := range cbs {
cb(cfg)
}
hs := &HTTPServer{
CacheService: localcache.New(5*time.Minute, 10*time.Minute),
Cfg: cfg,
SQLStore: dbtest.NewFakeDB(),
}
m.Get("/api/health", hs.apiHealthHandler)
return m, hs
}