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  }