| 
									
										
										
										
											2020-10-21 17:06:19 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"net/http/httptest" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/infra/localcache" | 
					
						
							| 
									
										
										
										
											2022-02-04 21:33:35 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/sqlstore/mockstore" | 
					
						
							| 
									
										
										
										
											2020-10-21 17:06:19 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/setting" | 
					
						
							| 
									
										
										
										
											2021-10-11 20:30:59 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/web" | 
					
						
							| 
									
										
										
										
											2020-10-21 17:06:19 +08:00
										 |  |  | 	"github.com/stretchr/testify/require" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestHealthAPI_Version(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2021-03-10 19:41:29 +08:00
										 |  |  | 	m, _ := setupHealthAPITestEnvironment(t, func(cfg *setting.Cfg) { | 
					
						
							|  |  |  | 		cfg.BuildVersion = "7.4.0" | 
					
						
							|  |  |  | 		cfg.BuildCommit = "59906ab1bf" | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2020-10-21 17:06:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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_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 | 
					
						
							| 
									
										
										
										
											2022-02-04 21:33:35 +08:00
										 |  |  | 	hs.SQLStore.(*mockstore.SQLStoreMock).ExpectedError = errors.New("bad") | 
					
						
							| 
									
										
										
										
											2020-10-21 17:06:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 20:30:59 +08:00
										 |  |  | func setupHealthAPITestEnvironment(t *testing.T, cbs ...func(*setting.Cfg)) (*web.Mux, *HTTPServer) { | 
					
						
							| 
									
										
										
										
											2020-10-21 17:06:19 +08:00
										 |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 20:30:59 +08:00
										 |  |  | 	m := web.New() | 
					
						
							| 
									
										
										
										
											2021-03-10 19:41:29 +08:00
										 |  |  | 	cfg := setting.NewCfg() | 
					
						
							|  |  |  | 	for _, cb := range cbs { | 
					
						
							|  |  |  | 		cb(cfg) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-21 17:06:19 +08:00
										 |  |  | 	hs := &HTTPServer{ | 
					
						
							|  |  |  | 		CacheService: localcache.New(5*time.Minute, 10*time.Minute), | 
					
						
							| 
									
										
										
										
											2021-03-10 19:41:29 +08:00
										 |  |  | 		Cfg:          cfg, | 
					
						
							| 
									
										
										
										
											2022-02-04 21:33:35 +08:00
										 |  |  | 		SQLStore:     mockstore.NewSQLStoreMock(), | 
					
						
							| 
									
										
										
										
											2020-10-21 17:06:19 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m.Get("/api/health", hs.apiHealthHandler) | 
					
						
							|  |  |  | 	return m, hs | 
					
						
							|  |  |  | } |