github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/querier/worker_service_test.go (about) 1 package querier 2 3 import ( 4 "net/http" 5 "net/http/httptest" 6 "testing" 7 8 "github.com/gorilla/mux" 9 "github.com/grafana/dskit/services" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 "github.com/weaveworks/common/middleware" 13 14 querier_worker "github.com/grafana/loki/pkg/querier/worker" 15 ) 16 17 func Test_InitQuerierService(t *testing.T) { 18 var mockQueryHandlers = map[string]http.Handler{ 19 "/loki/api/v1/query": http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 20 _, err := res.Write([]byte("test handler")) 21 require.NoError(t, err) 22 }), 23 } 24 25 var alwaysExternalHandlers = map[string]http.Handler{ 26 "/loki/api/v1/tail": http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 27 _, err := res.Write([]byte("test tail handler")) 28 require.NoError(t, err) 29 }), 30 } 31 32 testContext := func(config WorkerServiceConfig, authMiddleware middleware.Interface) (*mux.Router, services.Service) { 33 externalRouter := mux.NewRouter() 34 35 if authMiddleware == nil { 36 authMiddleware = middleware.Identity 37 } 38 39 querierWorkerService, err := InitWorkerService( 40 config, 41 nil, 42 mockQueryHandlers, 43 alwaysExternalHandlers, 44 externalRouter, 45 http.HandlerFunc(externalRouter.ServeHTTP), 46 authMiddleware, 47 ) 48 require.NoError(t, err) 49 50 return externalRouter, querierWorkerService 51 } 52 53 t.Run("when querier is configured to run standalone, without a query frontend", func(t *testing.T) { 54 t.Run("register the internal query handlers externally", func(t *testing.T) { 55 config := WorkerServiceConfig{ 56 QueryFrontendEnabled: false, 57 QuerySchedulerEnabled: false, 58 AllEnabled: false, 59 QuerierWorkerConfig: &querier_worker.Config{}, 60 } 61 62 externalRouter, _ := testContext(config, nil) 63 64 recorder := httptest.NewRecorder() 65 request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) 66 externalRouter.ServeHTTP(recorder, request) 67 assert.Equal(t, 200, recorder.Code) 68 assert.Equal(t, "test handler", recorder.Body.String()) 69 70 // Tail endpoints always external 71 recorder = httptest.NewRecorder() 72 request = httptest.NewRequest("GET", "/loki/api/v1/tail", nil) 73 externalRouter.ServeHTTP(recorder, request) 74 assert.Equal(t, 200, recorder.Code) 75 assert.Equal(t, "test tail handler", recorder.Body.String()) 76 }) 77 78 t.Run("wrap external handler with auth middleware", func(t *testing.T) { 79 config := WorkerServiceConfig{ 80 QueryFrontendEnabled: false, 81 QuerySchedulerEnabled: false, 82 AllEnabled: false, 83 QuerierWorkerConfig: &querier_worker.Config{}, 84 } 85 86 requestedAuthenticated := false 87 mockAuthMiddleware := middleware.Func(func(next http.Handler) http.Handler { 88 requestedAuthenticated = true 89 return next 90 }) 91 92 externalRouter, _ := testContext(config, mockAuthMiddleware) 93 94 recorder := httptest.NewRecorder() 95 request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) 96 externalRouter.ServeHTTP(recorder, request) 97 assert.True(t, requestedAuthenticated) 98 }) 99 100 t.Run("wrap external handler with response json middleware", func(t *testing.T) { 101 // note: this test only assures that the content type of the response is 102 // set if the handler function does not override it, which happens in the 103 // actual implementation, see 104 // https://github.com/grafana/loki/blob/34a012adcfade43291de3a7670f53679ea06aefe/pkg/lokifrontend/frontend/transport/handler.go#L136-L139 105 config := WorkerServiceConfig{ 106 QueryFrontendEnabled: false, 107 QuerySchedulerEnabled: false, 108 AllEnabled: false, 109 QuerierWorkerConfig: &querier_worker.Config{}, 110 } 111 112 externalRouter, _ := testContext(config, nil) 113 114 recorder := httptest.NewRecorder() 115 request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) 116 externalRouter.ServeHTTP(recorder, request) 117 118 contentTypeHeader := recorder.Header().Get("Content-Type") 119 assert.Equal(t, "application/json; charset=UTF-8", contentTypeHeader) 120 }) 121 122 t.Run("do not create a querier worker service if neither frontend address nor scheduler address has been configured", func(t *testing.T) { 123 config := WorkerServiceConfig{ 124 QueryFrontendEnabled: false, 125 QuerySchedulerEnabled: false, 126 AllEnabled: false, 127 QuerierWorkerConfig: &querier_worker.Config{}, 128 } 129 130 _, workerService := testContext(config, nil) 131 assert.Nil(t, workerService) 132 }) 133 134 t.Run("return a querier worker service if frontend or scheduler address has been configured", func(t *testing.T) { 135 withFrontendConfig := WorkerServiceConfig{ 136 QuerierWorkerConfig: &querier_worker.Config{ 137 FrontendAddress: "http://example.com", 138 }, 139 } 140 withSchedulerConfig := WorkerServiceConfig{ 141 QuerierWorkerConfig: &querier_worker.Config{ 142 SchedulerAddress: "http://example.com", 143 }, 144 } 145 146 for _, config := range []WorkerServiceConfig{ 147 withFrontendConfig, 148 withSchedulerConfig, 149 } { 150 _, workerService := testContext(config, nil) 151 assert.NotNil(t, workerService) 152 } 153 }) 154 }) 155 156 t.Run("when query frontend, scheduler, or all target is enabled", func(t *testing.T) { 157 defaultWorkerConfig := querier_worker.Config{} 158 nonStandaloneTargetPermutations := []WorkerServiceConfig{ 159 { 160 QueryFrontendEnabled: true, 161 QuerySchedulerEnabled: false, 162 AllEnabled: false, 163 QuerierWorkerConfig: &defaultWorkerConfig, 164 }, 165 { 166 QueryFrontendEnabled: false, 167 QuerySchedulerEnabled: true, 168 AllEnabled: false, 169 QuerierWorkerConfig: &defaultWorkerConfig, 170 }, 171 { 172 QueryFrontendEnabled: false, 173 QuerySchedulerEnabled: false, 174 AllEnabled: true, 175 QuerierWorkerConfig: &defaultWorkerConfig, 176 }, 177 { 178 QueryFrontendEnabled: true, 179 QuerySchedulerEnabled: true, 180 AllEnabled: false, 181 QuerierWorkerConfig: &defaultWorkerConfig, 182 }, 183 { 184 QueryFrontendEnabled: true, 185 QuerySchedulerEnabled: false, 186 AllEnabled: true, 187 QuerierWorkerConfig: &defaultWorkerConfig, 188 }, 189 { 190 QueryFrontendEnabled: false, 191 QuerySchedulerEnabled: true, 192 AllEnabled: true, 193 QuerierWorkerConfig: &defaultWorkerConfig, 194 }, 195 { 196 QueryFrontendEnabled: true, 197 QuerySchedulerEnabled: true, 198 AllEnabled: true, 199 QuerierWorkerConfig: &defaultWorkerConfig, 200 }, 201 } 202 203 t.Run("do not register the internal query handler externally", func(t *testing.T) { 204 for _, config := range nonStandaloneTargetPermutations { 205 externalRouter, _ := testContext(config, nil) 206 recorder := httptest.NewRecorder() 207 request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) 208 externalRouter.ServeHTTP(recorder, request) 209 assert.Equal(t, 404, recorder.Code) 210 211 // Tail endpoints always external 212 recorder = httptest.NewRecorder() 213 request = httptest.NewRequest("GET", "/loki/api/v1/tail", nil) 214 externalRouter.ServeHTTP(recorder, request) 215 assert.Equal(t, 200, recorder.Code) 216 assert.Equal(t, "test tail handler", recorder.Body.String()) 217 } 218 }) 219 220 t.Run("use localhost as the worker address if none is set", func(t *testing.T) { 221 for _, config := range nonStandaloneTargetPermutations { 222 workerConfig := querier_worker.Config{} 223 config.QuerierWorkerConfig = &workerConfig 224 config.GrpcListenPort = 1234 225 226 testContext(config, nil) 227 228 assert.Equal(t, "127.0.0.1:1234", workerConfig.FrontendAddress) 229 } 230 }) 231 232 t.Run("always return a query worker service", func(t *testing.T) { 233 for _, config := range nonStandaloneTargetPermutations { 234 workerConfig := querier_worker.Config{} 235 config.QuerierWorkerConfig = &workerConfig 236 config.GrpcListenPort = 1234 237 238 _, querierWorkerService := testContext(config, nil) 239 240 assert.NotNil(t, querierWorkerService) 241 } 242 }) 243 }) 244 }