diff --git a/go.mod b/go.mod index 3d55ba923c1..4496998f90f 100644 --- a/go.mod +++ b/go.mod @@ -88,7 +88,7 @@ require ( github.com/grafana/grafana-cloud-migration-snapshot v1.3.0 // @grafana/grafana-operator-experience-squad github.com/grafana/grafana-google-sdk-go v0.1.0 // @grafana/partner-datasources github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 // @grafana/grafana-backend-group - github.com/grafana/grafana-plugin-sdk-go v0.250.0 // @grafana/plugins-platform-backend + github.com/grafana/grafana-plugin-sdk-go v0.251.0 // @grafana/plugins-platform-backend github.com/grafana/grafana/pkg/aggregator v0.0.0-20240813192817-1b0e6b5c09b2 // @grafana/grafana-app-platform-squad github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240821155123-6891eb1d35da // @grafana/grafana-app-platform-squad github.com/grafana/grafana/pkg/apiserver v0.0.0-20240821155123-6891eb1d35da // @grafana/grafana-app-platform-squad diff --git a/go.sum b/go.sum index 143299e44c6..92daabd7e00 100644 --- a/go.sum +++ b/go.sum @@ -2293,8 +2293,8 @@ github.com/grafana/grafana-google-sdk-go v0.1.0/go.mod h1:Vo2TKWfDVmNTELBUM+3lkr github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 h1:r+mU5bGMzcXCRVAuOrTn54S80qbfVkvTdUJZfSfTNbs= github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79/go.mod h1:wc6Hbh3K2TgCUSfBC/BOzabItujtHMESZeFk5ZhdxhQ= github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk= -github.com/grafana/grafana-plugin-sdk-go v0.250.0 h1:9EBucp9jLqMx2b8NTlOXH+4OuQWUh6L85c6EJUN8Jdo= -github.com/grafana/grafana-plugin-sdk-go v0.250.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk= +github.com/grafana/grafana-plugin-sdk-go v0.251.0 h1:gnOtxrC/1rqFvpSbQYyoZqkr47oWDlz4Q2L6Ozmsi3w= +github.com/grafana/grafana-plugin-sdk-go v0.251.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk= github.com/grafana/grafana/apps/playlist v0.0.0-20240917082838-e2bce38a7990 h1:uQMZE/z+Y+o/U0z/g8ckAHss7U7LswedilByA2535DU= github.com/grafana/grafana/apps/playlist v0.0.0-20240917082838-e2bce38a7990/go.mod h1:3Vi0xv/4OBkBw4R9GAERkSrBnx06qrjpmNBRisucuSM= github.com/grafana/grafana/pkg/aggregator v0.0.0-20240813192817-1b0e6b5c09b2 h1:2H9x4q53pkfUGtSNYD1qSBpNnxrFgylof/TYADb5xMI= diff --git a/go.work.sum b/go.work.sum index ca6f13d695d..e993d1985f4 100644 --- a/go.work.sum +++ b/go.work.sum @@ -470,6 +470,8 @@ github.com/elastic/go-sysinfo v1.11.2/go.mod h1:GKqR8bbMK/1ITnez9NIsIfXQr25aLhRJ github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0= github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss= github.com/elazarl/goproxy v0.0.0-20230731152917-f99041a5c027/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= +github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= github.com/expr-lang/expr v1.16.2 h1:JvMnzUs3LeVHBvGFcXYmXo+Q6DPDmzrlcSBO6Wy3w4s= github.com/expr-lang/expr v1.16.2/go.mod h1:uCkhfG+x7fcZ5A5sXHKuQ07jGZRl6J0FCAaf2k4PtVQ= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= @@ -792,6 +794,7 @@ github.com/relvacode/iso8601 v1.4.0 h1:GsInVSEJfkYuirYFxa80nMLbH2aydgZpIf52gYZXU github.com/relvacode/iso8601 v1.4.0/go.mod h1:FlNp+jz+TXpyRqgmM7tnzHHzBnz776kmAH2h3sZCn0I= github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4 h1:BN/Nyn2nWMoqGRA7G7paDNDqTXE30mXGqzzybrfo05w= +github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 h1:K1Xf3bKttbF+koVGaX5xngRIZ5bVjbmPnaxE/dR08uY= @@ -995,11 +998,9 @@ golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= -golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1011,7 +1012,6 @@ golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -1023,14 +1023,12 @@ gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPj gonum.org/v1/plot v0.10.1 h1:dnifSs43YJuNMDzB7v8wV64O4ABBHReuAVAoBxqBqS4= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/genproto v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:mCr1K1c8kX+1iSBREvU3Juo11CB+QOEWxbRS01wWl5M= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:AHT0dDg3SoMOgZGnZk29b5xTbPHMoEC8qthmBLJCpys= google.golang.org/genproto/googleapis/api v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:OFMYQFHJ4TM3JRlWDZhJbZfra2uqc3WLBZiaaqP4DtU= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240730163845-b1a4ccb954bf h1:T4tsZBlZYXK3j40sQNP5MBO32I+rn6ypV1PpklsiV8k= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:5/MT647Cn/GGhwTpXC7QqcaR5Cnee4v4MKCU1/nwnIQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= diff --git a/pkg/aggregator/go.mod b/pkg/aggregator/go.mod index 6b0c3c779f7..a895aa18a63 100644 --- a/pkg/aggregator/go.mod +++ b/pkg/aggregator/go.mod @@ -4,7 +4,7 @@ go 1.23.1 require ( github.com/emicklei/go-restful/v3 v3.11.0 - github.com/grafana/grafana-plugin-sdk-go v0.250.0 + github.com/grafana/grafana-plugin-sdk-go v0.251.0 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435 github.com/grafana/grafana/pkg/semconv v0.0.0-20240808213237-f4d2e064f435 github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38 diff --git a/pkg/aggregator/go.sum b/pkg/aggregator/go.sum index 55fbbd6b5b2..758a214e167 100644 --- a/pkg/aggregator/go.sum +++ b/pkg/aggregator/go.sum @@ -130,8 +130,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grafana/grafana-plugin-sdk-go v0.250.0 h1:9EBucp9jLqMx2b8NTlOXH+4OuQWUh6L85c6EJUN8Jdo= -github.com/grafana/grafana-plugin-sdk-go v0.250.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk= +github.com/grafana/grafana-plugin-sdk-go v0.251.0 h1:gnOtxrC/1rqFvpSbQYyoZqkr47oWDlz4Q2L6Ozmsi3w= +github.com/grafana/grafana-plugin-sdk-go v0.251.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435 h1:lmw60EW7JWlAEvgggktOyVkH4hF1m/+LSF/Ap0NCyi8= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435/go.mod h1:ORVFiW/KNRY52lNjkGwnFWCxNVfE97bJG2jr2fetq0I= github.com/grafana/grafana/pkg/semconv v0.0.0-20240808213237-f4d2e064f435 h1:SNEeqY22DrGr5E9kGF1mKSqlOom14W9+b1u4XEGJowA= diff --git a/pkg/api/plugin_resource_test.go b/pkg/api/plugin_resource_test.go index a83a9400cc5..b628d35e85a 100644 --- a/pkg/api/plugin_resource_test.go +++ b/pkg/api/plugin_resource_test.go @@ -21,7 +21,6 @@ import ( "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin" - pluginClient "github.com/grafana/grafana/pkg/plugins/manager/client" "github.com/grafana/grafana/pkg/plugins/manager/fakes" "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/caching" @@ -172,7 +171,7 @@ func TestCallResource(t *testing.T) { }, })) middlewares := pluginsintegration.CreateMiddlewares(cfg, &oauthtokentest.Service{}, tracing.InitializeTracerForTest(), &caching.OSSCachingService{}, featuremgmt.WithFeatures(), prometheus.DefaultRegisterer, pluginRegistry) - pc, err := pluginClient.NewDecorator(&fakes.FakePluginClient{ + pc, err := backend.HandlerFromMiddlewares(&fakes.FakePluginClient{ CallResourceHandlerFunc: backend.CallResourceHandlerFunc(func(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { return errors.New("something went wrong") diff --git a/pkg/plugins/ifaces.go b/pkg/plugins/ifaces.go index 5606d4b6259..14684b3bc55 100644 --- a/pkg/plugins/ifaces.go +++ b/pkg/plugins/ifaces.go @@ -88,13 +88,7 @@ type FoundPlugin struct { // Client is used to communicate with backend plugin implementations. type Client interface { - backend.QueryDataHandler - backend.CheckHealthHandler - backend.StreamHandler - backend.AdmissionHandler - backend.ConversionHandler - backend.CallResourceHandler - backend.CollectMetricsHandler + backend.Handler } // BackendFactoryProvider provides a backend factory for a provided plugin. @@ -131,23 +125,6 @@ type Licensing interface { AppURL() string } -// ClientMiddleware is an interface representing the ability to create a middleware -// that implements the Client interface. -type ClientMiddleware interface { - // CreateClientMiddleware creates a new client middleware. - CreateClientMiddleware(next Client) Client -} - -// The ClientMiddlewareFunc type is an adapter to allow the use of ordinary -// functions as ClientMiddleware's. If f is a function with the appropriate -// signature, ClientMiddlewareFunc(f) is a ClientMiddleware that calls f. -type ClientMiddlewareFunc func(next Client) Client - -// CreateClientMiddleware implements the ClientMiddleware interface. -func (fn ClientMiddlewareFunc) CreateClientMiddleware(next Client) Client { - return fn(next) -} - type SignatureCalculator interface { Calculate(ctx context.Context, src PluginSource, plugin FoundPlugin) (Signature, error) } diff --git a/pkg/plugins/manager/client/client.go b/pkg/plugins/manager/client/client.go index 33753947c88..c6382451a87 100644 --- a/pkg/plugins/manager/client/client.go +++ b/pkg/plugins/manager/client/client.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/manager/registry" + "github.com/grafana/grafana/pkg/util/proxyutil" ) const ( @@ -101,8 +102,11 @@ func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceReq removeConnectionHeaders(res.Headers) removeHopByHopHeaders(res.Headers) removeNonAllowedHeaders(res.Headers) + } else { + res.Headers = map[string][]string{} } + proxyutil.SetProxyResponseHeaders(res.Headers) ensureContentTypeHeader(res) } diff --git a/pkg/plugins/manager/client/client_test.go b/pkg/plugins/manager/client/client_test.go index 20401d34250..420754059d2 100644 --- a/pkg/plugins/manager/client/client_test.go +++ b/pkg/plugins/manager/client/client_test.go @@ -310,6 +310,48 @@ func TestCallResource(t *testing.T) { require.Equal(t, "should not be deleted", res.Headers["X-Custom"][0]) }) + t.Run("Should set proxy response headers", func(t *testing.T) { + resHeaders := map[string][]string{ + "X-Custom": {"should not be deleted"}, + } + + req := &backend.CallResourceRequest{ + PluginContext: backend.PluginContext{ + PluginID: "pid", + }, + } + + responses := []*backend.CallResourceResponse{} + sender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error { + responses = append(responses, res) + return nil + }) + + p.RegisterClient(&fakePluginBackend{ + crr: func(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { + return sender.Send(&backend.CallResourceResponse{ + Headers: resHeaders, + Status: http.StatusOK, + Body: []byte(backendResponse), + }) + }, + }) + err := registry.Add(context.Background(), p) + require.NoError(t, err) + + client := ProvideService(registry) + + err = client.CallResource(context.Background(), req, sender) + require.NoError(t, err) + + require.Len(t, responses, 1) + res := responses[0] + require.Equal(t, http.StatusOK, res.Status) + require.Equal(t, []byte(backendResponse), res.Body) + require.Equal(t, "sandbox", res.Headers["Content-Security-Policy"][0]) + require.Equal(t, "should not be deleted", res.Headers["X-Custom"][0]) + }) + t.Run("Should ensure content type header", func(t *testing.T) { tcs := []struct { contentType string diff --git a/pkg/plugins/manager/client/clienttest/clienttest.go b/pkg/plugins/manager/client/clienttest/clienttest.go deleted file mode 100644 index 45886258a20..00000000000 --- a/pkg/plugins/manager/client/clienttest/clienttest.go +++ /dev/null @@ -1,331 +0,0 @@ -package clienttest - -import ( - "context" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/stretchr/testify/require" - - "github.com/grafana/grafana/pkg/plugins" - "github.com/grafana/grafana/pkg/plugins/manager/client" - "github.com/grafana/grafana/pkg/services/contexthandler/ctxkey" - contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" - "github.com/grafana/grafana/pkg/services/user" - "github.com/grafana/grafana/pkg/web" -) - -type TestClient struct { - plugins.Client - QueryDataFunc backend.QueryDataHandlerFunc - CallResourceFunc backend.CallResourceHandlerFunc - CheckHealthFunc backend.CheckHealthHandlerFunc - CollectMetricsFunc backend.CollectMetricsHandlerFunc - SubscribeStreamFunc func(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) - PublishStreamFunc func(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) - RunStreamFunc func(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error - ValidateAdmissionFunc backend.ValidateAdmissionFunc - MutateAdmissionFunc backend.MutateAdmissionFunc - ConvertObjectsFunc backend.ConvertObjectsFunc -} - -func (c *TestClient) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - if c.QueryDataFunc != nil { - return c.QueryDataFunc(ctx, req) - } - - return nil, nil -} - -func (c *TestClient) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { - if c.CallResourceFunc != nil { - return c.CallResourceFunc(ctx, req, sender) - } - - return nil -} - -func (c *TestClient) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { - if c.CheckHealthFunc != nil { - return c.CheckHealthFunc(ctx, req) - } - - return nil, nil -} - -func (c *TestClient) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) { - if c.CollectMetricsFunc != nil { - return c.CollectMetricsFunc(ctx, req) - } - - return nil, nil -} - -func (c *TestClient) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) { - if c.PublishStreamFunc != nil { - return c.PublishStreamFunc(ctx, req) - } - - return nil, nil -} - -func (c *TestClient) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) { - if c.SubscribeStreamFunc != nil { - return c.SubscribeStreamFunc(ctx, req) - } - - return nil, nil -} - -func (c *TestClient) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error { - if c.RunStreamFunc != nil { - return c.RunStreamFunc(ctx, req, sender) - } - return nil -} - -func (c *TestClient) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) { - if c.ValidateAdmissionFunc != nil { - return c.ValidateAdmissionFunc(ctx, req) - } - return nil, nil -} - -func (c *TestClient) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) { - if c.MutateAdmissionFunc != nil { - return c.MutateAdmissionFunc(ctx, req) - } - return nil, nil -} - -func (c *TestClient) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) { - if c.ConvertObjectsFunc != nil { - return c.ConvertObjectsFunc(ctx, req) - } - return nil, nil -} - -type MiddlewareScenarioContext struct { - QueryDataCallChain []string - CallResourceCallChain []string - CollectMetricsCallChain []string - CheckHealthCallChain []string - SubscribeStreamCallChain []string - PublishStreamCallChain []string - RunStreamCallChain []string - InstanceSettingsCallChain []string - ValidateAdmissionCallChain []string - MutateAdmissionCallChain []string - ConvertObjectsCallChain []string -} - -func (ctx *MiddlewareScenarioContext) NewMiddleware(name string) plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { - return &TestMiddleware{ - next: next, - Name: name, - sCtx: ctx, - } - }) -} - -type TestMiddleware struct { - next plugins.Client - sCtx *MiddlewareScenarioContext - Name string -} - -func (m *TestMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - m.sCtx.QueryDataCallChain = append(m.sCtx.QueryDataCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.QueryData(ctx, req) - m.sCtx.QueryDataCallChain = append(m.sCtx.QueryDataCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { - m.sCtx.CallResourceCallChain = append(m.sCtx.CallResourceCallChain, fmt.Sprintf("before %s", m.Name)) - err := m.next.CallResource(ctx, req, sender) - m.sCtx.CallResourceCallChain = append(m.sCtx.CallResourceCallChain, fmt.Sprintf("after %s", m.Name)) - return err -} - -func (m *TestMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) { - m.sCtx.CollectMetricsCallChain = append(m.sCtx.CollectMetricsCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.CollectMetrics(ctx, req) - m.sCtx.CollectMetricsCallChain = append(m.sCtx.CollectMetricsCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) { - m.sCtx.ValidateAdmissionCallChain = append(m.sCtx.ValidateAdmissionCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.ValidateAdmission(ctx, req) - m.sCtx.ValidateAdmissionCallChain = append(m.sCtx.ValidateAdmissionCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) { - m.sCtx.MutateAdmissionCallChain = append(m.sCtx.MutateAdmissionCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.MutateAdmission(ctx, req) - m.sCtx.MutateAdmissionCallChain = append(m.sCtx.MutateAdmissionCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) { - m.sCtx.ConvertObjectsCallChain = append(m.sCtx.ConvertObjectsCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.ConvertObjects(ctx, req) - m.sCtx.ConvertObjectsCallChain = append(m.sCtx.ConvertObjectsCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { - m.sCtx.CheckHealthCallChain = append(m.sCtx.CheckHealthCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.CheckHealth(ctx, req) - m.sCtx.CheckHealthCallChain = append(m.sCtx.CheckHealthCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) { - m.sCtx.SubscribeStreamCallChain = append(m.sCtx.SubscribeStreamCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.SubscribeStream(ctx, req) - m.sCtx.SubscribeStreamCallChain = append(m.sCtx.SubscribeStreamCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) { - m.sCtx.PublishStreamCallChain = append(m.sCtx.PublishStreamCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.PublishStream(ctx, req) - m.sCtx.PublishStreamCallChain = append(m.sCtx.PublishStreamCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error { - m.sCtx.RunStreamCallChain = append(m.sCtx.RunStreamCallChain, fmt.Sprintf("before %s", m.Name)) - err := m.next.RunStream(ctx, req, sender) - m.sCtx.RunStreamCallChain = append(m.sCtx.RunStreamCallChain, fmt.Sprintf("after %s", m.Name)) - return err -} - -var _ plugins.Client = &TestClient{} - -type ClientDecoratorTest struct { - T *testing.T - Context context.Context - TestClient *TestClient - Middlewares []plugins.ClientMiddleware - Decorator *client.Decorator - ReqContext *contextmodel.ReqContext - QueryDataReq *backend.QueryDataRequest - QueryDataCtx context.Context - CallResourceReq *backend.CallResourceRequest - CallResourceCtx context.Context - CheckHealthReq *backend.CheckHealthRequest - CheckHealthCtx context.Context - CollectMetricsReq *backend.CollectMetricsRequest - CollectMetricsCtx context.Context - SubscribeStreamReq *backend.SubscribeStreamRequest - SubscribeStreamCtx context.Context - PublishStreamReq *backend.PublishStreamRequest - PublishStreamCtx context.Context - - // When CallResource is called, the sender will be called with these values - callResourceResponses []*backend.CallResourceResponse -} - -type ClientDecoratorTestOption func(*ClientDecoratorTest) - -func NewClientDecoratorTest(t *testing.T, opts ...ClientDecoratorTestOption) *ClientDecoratorTest { - cdt := &ClientDecoratorTest{ - T: t, - Context: context.Background(), - } - cdt.TestClient = &TestClient{ - QueryDataFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - cdt.QueryDataReq = req - cdt.QueryDataCtx = ctx - return nil, nil - }, - CallResourceFunc: func(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { - cdt.CallResourceReq = req - cdt.CallResourceCtx = ctx - if cdt.callResourceResponses != nil { - for _, r := range cdt.callResourceResponses { - if err := sender.Send(r); err != nil { - return err - } - } - } - return nil - }, - CheckHealthFunc: func(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { - cdt.CheckHealthReq = req - cdt.CheckHealthCtx = ctx - return nil, nil - }, - CollectMetricsFunc: func(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) { - cdt.CollectMetricsReq = req - cdt.CollectMetricsCtx = ctx - return nil, nil - }, - SubscribeStreamFunc: func(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) { - cdt.SubscribeStreamReq = req - cdt.SubscribeStreamCtx = ctx - return nil, nil - }, - PublishStreamFunc: func(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) { - cdt.PublishStreamReq = req - cdt.PublishStreamCtx = ctx - return nil, nil - }, - } - require.NotNil(t, cdt) - - for _, opt := range opts { - opt(cdt) - } - - d, err := client.NewDecorator(cdt.TestClient, cdt.Middlewares...) - require.NoError(t, err) - require.NotNil(t, d) - - cdt.Decorator = d - - return cdt -} - -func WithReqContext(req *http.Request, user *user.SignedInUser) ClientDecoratorTestOption { - return ClientDecoratorTestOption(func(cdt *ClientDecoratorTest) { - if cdt.ReqContext == nil { - cdt.ReqContext = &contextmodel.ReqContext{ - Context: &web.Context{ - Resp: web.NewResponseWriter(req.Method, httptest.NewRecorder()), - }, - SignedInUser: user, - } - } - - cdt.Context = ctxkey.Set(cdt.Context, cdt.ReqContext) - - *req = *req.WithContext(cdt.Context) - cdt.ReqContext.Req = req - }) -} - -func WithMiddlewares(middlewares ...plugins.ClientMiddleware) ClientDecoratorTestOption { - return ClientDecoratorTestOption(func(cdt *ClientDecoratorTest) { - if cdt.Middlewares == nil { - cdt.Middlewares = []plugins.ClientMiddleware{} - } - - cdt.Middlewares = append(cdt.Middlewares, middlewares...) - }) -} - -// WithResourceResponses can be used to make the test client send simulated resource responses back over the sender stream -func WithResourceResponses(responses []*backend.CallResourceResponse) ClientDecoratorTestOption { - return ClientDecoratorTestOption(func(cdt *ClientDecoratorTest) { - cdt.callResourceResponses = responses - }) -} diff --git a/pkg/plugins/manager/client/decorator.go b/pkg/plugins/manager/client/decorator.go deleted file mode 100644 index 90a679d5ebe..00000000000 --- a/pkg/plugins/manager/client/decorator.go +++ /dev/null @@ -1,196 +0,0 @@ -package client - -import ( - "context" - "errors" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - - "github.com/grafana/grafana/pkg/plugins" -) - -// Decorator allows a plugins.Client to be decorated with middlewares. -type Decorator struct { - client plugins.Client - middlewares []plugins.ClientMiddleware -} - -var ( - _ = plugins.Client(&Decorator{}) -) - -// NewDecorator creates a new plugins.client decorator. -func NewDecorator(client plugins.Client, middlewares ...plugins.ClientMiddleware) (*Decorator, error) { - if client == nil { - return nil, errors.New("client cannot be nil") - } - - return &Decorator{ - client: client, - middlewares: middlewares, - }, nil -} - -func (d *Decorator) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - if req == nil { - return nil, errNilRequest - } - ctx = backend.WithEndpoint(ctx, backend.EndpointQueryData) - ctx = backend.WithPluginContext(ctx, req.PluginContext) - ctx = backend.WithUser(ctx, req.PluginContext.User) - - client := clientFromMiddlewares(d.middlewares, d.client) - - return client.QueryData(ctx, req) -} - -func (d *Decorator) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { - if req == nil { - return errNilRequest - } - - ctx = backend.WithEndpoint(ctx, backend.EndpointCallResource) - ctx = backend.WithPluginContext(ctx, req.PluginContext) - ctx = backend.WithUser(ctx, req.PluginContext.User) - - if sender == nil { - return errors.New("sender cannot be nil") - } - - client := clientFromMiddlewares(d.middlewares, d.client) - return client.CallResource(ctx, req, sender) -} - -func (d *Decorator) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) { - if req == nil { - return nil, errNilRequest - } - - ctx = backend.WithEndpoint(ctx, backend.EndpointCollectMetrics) - ctx = backend.WithPluginContext(ctx, req.PluginContext) - ctx = backend.WithUser(ctx, req.PluginContext.User) - - client := clientFromMiddlewares(d.middlewares, d.client) - return client.CollectMetrics(ctx, req) -} - -func (d *Decorator) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { - if req == nil { - return nil, errNilRequest - } - - ctx = backend.WithEndpoint(ctx, backend.EndpointCheckHealth) - ctx = backend.WithPluginContext(ctx, req.PluginContext) - ctx = backend.WithUser(ctx, req.PluginContext.User) - - client := clientFromMiddlewares(d.middlewares, d.client) - return client.CheckHealth(ctx, req) -} - -func (d *Decorator) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) { - if req == nil { - return nil, errNilRequest - } - - ctx = backend.WithEndpoint(ctx, backend.EndpointSubscribeStream) - ctx = backend.WithPluginContext(ctx, req.PluginContext) - ctx = backend.WithUser(ctx, req.PluginContext.User) - - client := clientFromMiddlewares(d.middlewares, d.client) - return client.SubscribeStream(ctx, req) -} - -func (d *Decorator) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) { - if req == nil { - return nil, errNilRequest - } - - ctx = backend.WithEndpoint(ctx, backend.EndpointPublishStream) - ctx = backend.WithPluginContext(ctx, req.PluginContext) - ctx = backend.WithUser(ctx, req.PluginContext.User) - - client := clientFromMiddlewares(d.middlewares, d.client) - return client.PublishStream(ctx, req) -} - -func (d *Decorator) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error { - if req == nil { - return errNilRequest - } - - ctx = backend.WithEndpoint(ctx, backend.EndpointRunStream) - ctx = backend.WithPluginContext(ctx, req.PluginContext) - ctx = backend.WithUser(ctx, req.PluginContext.User) - - if sender == nil { - return errors.New("sender cannot be nil") - } - - client := clientFromMiddlewares(d.middlewares, d.client) - return client.RunStream(ctx, req, sender) -} - -func (d *Decorator) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) { - if req == nil { - return nil, errNilRequest - } - - ctx = backend.WithEndpoint(ctx, backend.EndpointValidateAdmission) - ctx = backend.WithPluginContext(ctx, req.PluginContext) - ctx = backend.WithUser(ctx, req.PluginContext.User) - - client := clientFromMiddlewares(d.middlewares, d.client) - return client.ValidateAdmission(ctx, req) -} - -func (d *Decorator) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) { - if req == nil { - return nil, errNilRequest - } - - ctx = backend.WithEndpoint(ctx, backend.EndpointMutateAdmission) - ctx = backend.WithPluginContext(ctx, req.PluginContext) - ctx = backend.WithUser(ctx, req.PluginContext.User) - - client := clientFromMiddlewares(d.middlewares, d.client) - return client.MutateAdmission(ctx, req) -} - -func (d *Decorator) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) { - if req == nil { - return nil, errNilRequest - } - - ctx = backend.WithEndpoint(ctx, backend.EndpointConvertObject) - ctx = backend.WithPluginContext(ctx, req.PluginContext) - ctx = backend.WithUser(ctx, req.PluginContext.User) - - client := clientFromMiddlewares(d.middlewares, d.client) - return client.ConvertObjects(ctx, req) -} - -func clientFromMiddlewares(middlewares []plugins.ClientMiddleware, finalClient plugins.Client) plugins.Client { - if len(middlewares) == 0 { - return finalClient - } - - reversed := reverseMiddlewares(middlewares) - next := finalClient - - for _, m := range reversed { - next = m.CreateClientMiddleware(next) - } - - return next -} - -func reverseMiddlewares(middlewares []plugins.ClientMiddleware) []plugins.ClientMiddleware { - reversed := make([]plugins.ClientMiddleware, len(middlewares)) - copy(reversed, middlewares) - - for i, j := 0, len(reversed)-1; i < j; i, j = i+1, j-1 { - reversed[i], reversed[j] = reversed[j], reversed[i] - } - - return reversed -} diff --git a/pkg/plugins/manager/client/decorator_test.go b/pkg/plugins/manager/client/decorator_test.go deleted file mode 100644 index 5ed063233e7..00000000000 --- a/pkg/plugins/manager/client/decorator_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package client - -import ( - "context" - "fmt" - "testing" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/stretchr/testify/require" - - "github.com/grafana/grafana/pkg/plugins" -) - -func TestDecorator(t *testing.T) { - var queryDataCalled bool - var callResourceCalled bool - var checkHealthCalled bool - c := &TestClient{ - QueryDataFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - queryDataCalled = true - return nil, nil - }, - CallResourceFunc: func(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { - callResourceCalled = true - return nil - }, - CheckHealthFunc: func(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { - checkHealthCalled = true - return nil, nil - }, - } - require.NotNil(t, c) - - ctx := MiddlewareScenarioContext{} - - mwOne := ctx.NewMiddleware("mw1") - mwTwo := ctx.NewMiddleware("mw2") - - d, err := NewDecorator(c, mwOne, mwTwo) - require.NoError(t, err) - require.NotNil(t, d) - - _, _ = d.QueryData(context.Background(), &backend.QueryDataRequest{}) - require.True(t, queryDataCalled) - - sender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error { - return nil - }) - - _ = d.CallResource(context.Background(), &backend.CallResourceRequest{}, sender) - require.True(t, callResourceCalled) - - _, _ = d.CheckHealth(context.Background(), &backend.CheckHealthRequest{}) - require.True(t, checkHealthCalled) - - require.Len(t, ctx.QueryDataCallChain, 4) - require.EqualValues(t, []string{"before mw1", "before mw2", "after mw2", "after mw1"}, ctx.QueryDataCallChain) - require.Len(t, ctx.CallResourceCallChain, 4) - require.EqualValues(t, []string{"before mw1", "before mw2", "after mw2", "after mw1"}, ctx.CallResourceCallChain) - require.Len(t, ctx.CheckHealthCallChain, 4) - require.EqualValues(t, []string{"before mw1", "before mw2", "after mw2", "after mw1"}, ctx.CheckHealthCallChain) -} - -func TestReverseMiddlewares(t *testing.T) { - t.Run("Should reverse 1 middleware", func(t *testing.T) { - ctx := MiddlewareScenarioContext{} - middlewares := []plugins.ClientMiddleware{ - ctx.NewMiddleware("mw1"), - } - reversed := reverseMiddlewares(middlewares) - require.Len(t, reversed, 1) - require.Equal(t, "mw1", reversed[0].CreateClientMiddleware(nil).(*TestMiddleware).Name) - }) - - t.Run("Should reverse 2 middlewares", func(t *testing.T) { - ctx := MiddlewareScenarioContext{} - middlewares := []plugins.ClientMiddleware{ - ctx.NewMiddleware("mw1"), - ctx.NewMiddleware("mw2"), - } - reversed := reverseMiddlewares(middlewares) - require.Len(t, reversed, 2) - require.Equal(t, "mw2", reversed[0].CreateClientMiddleware(nil).(*TestMiddleware).Name) - require.Equal(t, "mw1", reversed[1].CreateClientMiddleware(nil).(*TestMiddleware).Name) - }) - - t.Run("Should reverse 3 middlewares", func(t *testing.T) { - ctx := MiddlewareScenarioContext{} - middlewares := []plugins.ClientMiddleware{ - ctx.NewMiddleware("mw1"), - ctx.NewMiddleware("mw2"), - ctx.NewMiddleware("mw3"), - } - reversed := reverseMiddlewares(middlewares) - require.Len(t, reversed, 3) - require.Equal(t, "mw3", reversed[0].CreateClientMiddleware(nil).(*TestMiddleware).Name) - require.Equal(t, "mw2", reversed[1].CreateClientMiddleware(nil).(*TestMiddleware).Name) - require.Equal(t, "mw1", reversed[2].CreateClientMiddleware(nil).(*TestMiddleware).Name) - }) - - t.Run("Should reverse 4 middlewares", func(t *testing.T) { - ctx := MiddlewareScenarioContext{} - middlewares := []plugins.ClientMiddleware{ - ctx.NewMiddleware("mw1"), - ctx.NewMiddleware("mw2"), - ctx.NewMiddleware("mw3"), - ctx.NewMiddleware("mw4"), - } - reversed := reverseMiddlewares(middlewares) - require.Len(t, reversed, 4) - require.Equal(t, "mw4", reversed[0].CreateClientMiddleware(nil).(*TestMiddleware).Name) - require.Equal(t, "mw3", reversed[1].CreateClientMiddleware(nil).(*TestMiddleware).Name) - require.Equal(t, "mw2", reversed[2].CreateClientMiddleware(nil).(*TestMiddleware).Name) - require.Equal(t, "mw1", reversed[3].CreateClientMiddleware(nil).(*TestMiddleware).Name) - }) -} - -type TestClient struct { - plugins.Client - QueryDataFunc backend.QueryDataHandlerFunc - CallResourceFunc backend.CallResourceHandlerFunc - CheckHealthFunc backend.CheckHealthHandlerFunc -} - -func (c *TestClient) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - if c.QueryDataFunc != nil { - return c.QueryDataFunc(ctx, req) - } - - return nil, nil -} - -func (c *TestClient) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { - if c.CallResourceFunc != nil { - return c.CallResourceFunc(ctx, req, sender) - } - - return nil -} - -func (c *TestClient) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { - if c.CheckHealthFunc != nil { - return c.CheckHealthFunc(ctx, req) - } - - return nil, nil -} - -type MiddlewareScenarioContext struct { - QueryDataCallChain []string - CallResourceCallChain []string - CollectMetricsCallChain []string - CheckHealthCallChain []string - SubscribeStreamCallChain []string - PublishStreamCallChain []string - RunStreamCallChain []string - InstanceSettingsCallChain []string - ValidateAdmissionCallChain []string - MutateAdmissionCallChain []string - ConvertObjectCallChain []string -} - -func (ctx *MiddlewareScenarioContext) NewMiddleware(name string) plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { - return &TestMiddleware{ - next: next, - Name: name, - sCtx: ctx, - } - }) -} - -type TestMiddleware struct { - next plugins.Client - sCtx *MiddlewareScenarioContext - Name string -} - -func (m *TestMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - m.sCtx.QueryDataCallChain = append(m.sCtx.QueryDataCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.QueryData(ctx, req) - m.sCtx.QueryDataCallChain = append(m.sCtx.QueryDataCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { - m.sCtx.CallResourceCallChain = append(m.sCtx.CallResourceCallChain, fmt.Sprintf("before %s", m.Name)) - err := m.next.CallResource(ctx, req, sender) - m.sCtx.CallResourceCallChain = append(m.sCtx.CallResourceCallChain, fmt.Sprintf("after %s", m.Name)) - return err -} - -func (m *TestMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) { - m.sCtx.CollectMetricsCallChain = append(m.sCtx.CollectMetricsCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.CollectMetrics(ctx, req) - m.sCtx.CollectMetricsCallChain = append(m.sCtx.CollectMetricsCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { - m.sCtx.CheckHealthCallChain = append(m.sCtx.CheckHealthCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.CheckHealth(ctx, req) - m.sCtx.CheckHealthCallChain = append(m.sCtx.CheckHealthCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) { - m.sCtx.SubscribeStreamCallChain = append(m.sCtx.SubscribeStreamCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.SubscribeStream(ctx, req) - m.sCtx.SubscribeStreamCallChain = append(m.sCtx.SubscribeStreamCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) { - m.sCtx.PublishStreamCallChain = append(m.sCtx.PublishStreamCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.PublishStream(ctx, req) - m.sCtx.PublishStreamCallChain = append(m.sCtx.PublishStreamCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error { - m.sCtx.RunStreamCallChain = append(m.sCtx.RunStreamCallChain, fmt.Sprintf("before %s", m.Name)) - err := m.next.RunStream(ctx, req, sender) - m.sCtx.RunStreamCallChain = append(m.sCtx.RunStreamCallChain, fmt.Sprintf("after %s", m.Name)) - return err -} - -func (m *TestMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) { - m.sCtx.ValidateAdmissionCallChain = append(m.sCtx.ValidateAdmissionCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.ValidateAdmission(ctx, req) - m.sCtx.ValidateAdmissionCallChain = append(m.sCtx.ValidateAdmissionCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) { - m.sCtx.MutateAdmissionCallChain = append(m.sCtx.MutateAdmissionCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.MutateAdmission(ctx, req) - m.sCtx.MutateAdmissionCallChain = append(m.sCtx.MutateAdmissionCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -func (m *TestMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) { - m.sCtx.ConvertObjectCallChain = append(m.sCtx.ConvertObjectCallChain, fmt.Sprintf("before %s", m.Name)) - res, err := m.next.ConvertObjects(ctx, req) - m.sCtx.ConvertObjectCallChain = append(m.sCtx.ConvertObjectCallChain, fmt.Sprintf("after %s", m.Name)) - return res, err -} - -var _ plugins.Client = &TestClient{} diff --git a/pkg/promlib/go.mod b/pkg/promlib/go.mod index ba5b99a39c3..81f09839646 100644 --- a/pkg/promlib/go.mod +++ b/pkg/promlib/go.mod @@ -4,7 +4,7 @@ go 1.23.1 require ( github.com/grafana/dskit v0.0.0-20240805174438-dfa83b4ed2d3 - github.com/grafana/grafana-plugin-sdk-go v0.250.0 + github.com/grafana/grafana-plugin-sdk-go v0.251.0 github.com/json-iterator/go v1.1.12 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/prometheus/client_golang v1.20.3 diff --git a/pkg/promlib/go.sum b/pkg/promlib/go.sum index ae0bdbf758b..9d75718ccf1 100644 --- a/pkg/promlib/go.sum +++ b/pkg/promlib/go.sum @@ -98,8 +98,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/grafana/dskit v0.0.0-20240805174438-dfa83b4ed2d3 h1:as4PmrFoYI1byS5JjsgPC7uSGTMh+SgS0ePv6hOyDGU= github.com/grafana/dskit v0.0.0-20240805174438-dfa83b4ed2d3/go.mod h1:lcjGB6SuaZ2o44A9nD6p/tR4QXSPbzViRY520Gy6pTQ= -github.com/grafana/grafana-plugin-sdk-go v0.250.0 h1:9EBucp9jLqMx2b8NTlOXH+4OuQWUh6L85c6EJUN8Jdo= -github.com/grafana/grafana-plugin-sdk-go v0.250.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk= +github.com/grafana/grafana-plugin-sdk-go v0.251.0 h1:gnOtxrC/1rqFvpSbQYyoZqkr47oWDlz4Q2L6Ozmsi3w= +github.com/grafana/grafana-plugin-sdk-go v0.251.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk= github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= diff --git a/pkg/services/pluginsintegration/clientmiddleware/base_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/base_middleware.go deleted file mode 100644 index 32a795a5477..00000000000 --- a/pkg/services/pluginsintegration/clientmiddleware/base_middleware.go +++ /dev/null @@ -1,60 +0,0 @@ -package clientmiddleware - -import ( - "context" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - - "github.com/grafana/grafana/pkg/plugins" -) - -var _ = plugins.Client(&baseMiddleware{}) - -// The base middleware simply passes the request down the chain -// This allows middleware to avoid implementing all the noop functions -type baseMiddleware struct { - next plugins.Client -} - -func (m *baseMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - return m.next.QueryData(ctx, req) -} - -func (m *baseMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { - return m.next.CallResource(ctx, req, sender) -} - -func (m *baseMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { - return m.next.CheckHealth(ctx, req) -} - -func (m *baseMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) { - return m.next.CollectMetrics(ctx, req) -} - -func (m *baseMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) { - return m.next.SubscribeStream(ctx, req) -} - -func (m *baseMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) { - return m.next.PublishStream(ctx, req) -} - -func (m *baseMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error { - return m.next.RunStream(ctx, req, sender) -} - -// ValidateAdmission implements backend.AdmissionHandler. -func (m *baseMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) { - return m.next.ValidateAdmission(ctx, req) -} - -// MutateAdmission implements backend.AdmissionHandler. -func (m *baseMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) { - return m.next.MutateAdmission(ctx, req) -} - -// ConvertObject implements backend.AdmissionHandler. -func (m *baseMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) { - return m.next.ConvertObjects(ctx, req) -} diff --git a/pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go index 95756b169af..80058c0a5e8 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go @@ -10,7 +10,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/caching" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/featuremgmt" @@ -19,15 +18,15 @@ import ( // needed to mock the function for testing var shouldCacheQuery = awsds.ShouldCacheQuery -// NewCachingMiddleware creates a new plugins.ClientMiddleware that will +// NewCachingMiddleware creates a new backend.HandlerMiddleware that will // attempt to read and write query results to the cache -func NewCachingMiddleware(cachingService caching.CachingService) plugins.ClientMiddleware { +func NewCachingMiddleware(cachingService caching.CachingService) backend.HandlerMiddleware { return NewCachingMiddlewareWithFeatureManager(cachingService, nil) } -// NewCachingMiddlewareWithFeatureManager creates a new plugins.ClientMiddleware that will +// NewCachingMiddlewareWithFeatureManager creates a new backend.HandlerMiddleware that will // attempt to read and write query results to the cache with a feature manager -func NewCachingMiddlewareWithFeatureManager(cachingService caching.CachingService, features featuremgmt.FeatureToggles) plugins.ClientMiddleware { +func NewCachingMiddlewareWithFeatureManager(cachingService caching.CachingService, features featuremgmt.FeatureToggles) backend.HandlerMiddleware { log := log.New("caching_middleware") if err := prometheus.Register(QueryCachingRequestHistogram); err != nil { log.Error("Error registering prometheus collector 'QueryRequestHistogram'", "error", err) @@ -35,20 +34,18 @@ func NewCachingMiddlewareWithFeatureManager(cachingService caching.CachingServic if err := prometheus.Register(ResourceCachingRequestHistogram); err != nil { log.Error("Error registering prometheus collector 'ResourceRequestHistogram'", "error", err) } - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &CachingMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, - caching: cachingService, - log: log, - features: features, + BaseHandler: backend.NewBaseHandler(next), + caching: cachingService, + log: log, + features: features, } }) } type CachingMiddleware struct { - baseMiddleware + backend.BaseHandler caching caching.CachingService log log.Logger @@ -60,12 +57,12 @@ type CachingMiddleware struct { // If the cache service is implemented, we capture the request duration as a metric. The service is expected to write any response headers. func (m *CachingMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { if req == nil { - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } reqCtx := contexthandler.FromContext(ctx) if reqCtx == nil { - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } // time how long this request takes @@ -92,7 +89,7 @@ func (m *CachingMiddleware) QueryData(ctx context.Context, req *backend.QueryDat } // Cache miss; do the actual queries - resp, err := m.next.QueryData(ctx, req) + resp, err := m.BaseHandler.QueryData(ctx, req) // Update the query cache with the result for this metrics request if err == nil && cr.UpdateCacheFn != nil { @@ -125,12 +122,12 @@ func (m *CachingMiddleware) QueryData(ctx context.Context, req *backend.QueryDat // If the cache service is implemented, we capture the request duration as a metric. The service is expected to write any response headers. func (m *CachingMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { if req == nil { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } reqCtx := contexthandler.FromContext(ctx) if reqCtx == nil { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } // time how long this request takes @@ -157,7 +154,7 @@ func (m *CachingMiddleware) CallResource(ctx context.Context, req *backend.CallR // Cache miss; do the actual request // If there is no update cache func, just pass in the original sender if cr.UpdateCacheFn == nil { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } // Otherwise, intercept the responses in a wrapped sender so we can cache them first cacheSender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error { @@ -165,5 +162,5 @@ func (m *CachingMiddleware) CallResource(ctx context.Context, req *backend.CallR return sender.Send(res) }) - return m.next.CallResource(ctx, req, cacheSender) + return m.BaseHandler.CallResource(ctx, req, cacheSender) } diff --git a/pkg/services/pluginsintegration/clientmiddleware/caching_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/caching_middleware_test.go index 5a54eafc775..548f7a693bf 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/caching_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/caching_middleware_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/grafana/grafana/pkg/services/caching" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/featuremgmt" @@ -22,9 +22,9 @@ func TestCachingMiddleware(t *testing.T) { require.NoError(t, err) cs := caching.NewFakeOSSCachingService() - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewCachingMiddleware(cs)), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewCachingMiddleware(cs)), ) jsonDataMap := map[string]any{} @@ -63,7 +63,7 @@ func TestCachingMiddleware(t *testing.T) { cs.ReturnHit = true cs.ReturnQueryResponse = dataResponse - resp, err := cdt.Decorator.QueryData(req.Context(), qdr) + resp, err := cdt.MiddlewareHandler.QueryData(req.Context(), qdr) assert.NoError(t, err) // Cache service is called once cs.AssertCalls(t, "HandleQueryRequest", 1) @@ -92,7 +92,7 @@ func TestCachingMiddleware(t *testing.T) { cs.ReturnHit = false cs.ReturnQueryResponse = dataResponse - resp, err := cdt.Decorator.QueryData(req.Context(), qdr) + resp, err := cdt.MiddlewareHandler.QueryData(req.Context(), qdr) assert.NoError(t, err) // Cache service is called once cs.AssertCalls(t, "HandleQueryRequest", 1) @@ -105,9 +105,9 @@ func TestCachingMiddleware(t *testing.T) { }) t.Run("with async queries", func(t *testing.T) { - asyncCdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares( + asyncCdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares( NewCachingMiddlewareWithFeatureManager(cs, featuremgmt.WithFeatures(featuremgmt.FlagAwsAsyncQueryCaching))), ) t.Run("If shoudCacheQuery returns true update cache function is called", func(t *testing.T) { @@ -128,7 +128,7 @@ func TestCachingMiddleware(t *testing.T) { cs.ReturnHit = false cs.ReturnQueryResponse = dataResponse - resp, err := asyncCdt.Decorator.QueryData(req.Context(), qdr) + resp, err := asyncCdt.MiddlewareHandler.QueryData(req.Context(), qdr) assert.NoError(t, err) // Cache service is called once cs.AssertCalls(t, "HandleQueryRequest", 1) @@ -158,7 +158,7 @@ func TestCachingMiddleware(t *testing.T) { cs.ReturnHit = false cs.ReturnQueryResponse = dataResponse - resp, err := asyncCdt.Decorator.QueryData(req.Context(), qdr) + resp, err := asyncCdt.MiddlewareHandler.QueryData(req.Context(), qdr) assert.NoError(t, err) // Cache service is called once cs.AssertCalls(t, "HandleQueryRequest", 1) @@ -196,10 +196,10 @@ func TestCachingMiddleware(t *testing.T) { } cs := caching.NewFakeOSSCachingService() - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewCachingMiddleware(cs)), - clienttest.WithResourceResponses([]*backend.CallResourceResponse{simulatedPluginResponse}), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewCachingMiddleware(cs)), + handlertest.WithResourceResponses([]*backend.CallResourceResponse{simulatedPluginResponse}), ) jsonDataMap := map[string]any{} @@ -235,7 +235,7 @@ func TestCachingMiddleware(t *testing.T) { cs.ReturnHit = true cs.ReturnResourceResponse = dataResponse - err := cdt.Decorator.CallResource(req.Context(), crr, storeOneResponseCallResourceSender) + err := cdt.MiddlewareHandler.CallResource(req.Context(), crr, storeOneResponseCallResourceSender) assert.NoError(t, err) // Cache service is called once cs.AssertCalls(t, "HandleResourceRequest", 1) @@ -255,7 +255,7 @@ func TestCachingMiddleware(t *testing.T) { cs.ReturnHit = false cs.ReturnResourceResponse = dataResponse - err := cdt.Decorator.CallResource(req.Context(), crr, storeOneResponseCallResourceSender) + err := cdt.MiddlewareHandler.CallResource(req.Context(), crr, storeOneResponseCallResourceSender) assert.NoError(t, err) // Cache service is called once cs.AssertCalls(t, "HandleResourceRequest", 1) @@ -272,9 +272,9 @@ func TestCachingMiddleware(t *testing.T) { require.NoError(t, err) cs := caching.NewFakeOSSCachingService() - cdt := clienttest.NewClientDecoratorTest(t, + cdt := handlertest.NewHandlerMiddlewareTest(t, // Skip the request context in this case - clienttest.WithMiddlewares(NewCachingMiddleware(cs)), + handlertest.WithMiddlewares(NewCachingMiddleware(cs)), ) reqCtx := contexthandler.FromContext(req.Context()) require.Nil(t, reqCtx) @@ -298,7 +298,7 @@ func TestCachingMiddleware(t *testing.T) { PluginContext: pluginCtx, } - resp, err := cdt.Decorator.QueryData(context.Background(), qdr) + resp, err := cdt.MiddlewareHandler.QueryData(context.Background(), qdr) assert.NoError(t, err) // Cache service is never called cs.AssertCalls(t, "HandleQueryRequest", 0) @@ -315,7 +315,7 @@ func TestCachingMiddleware(t *testing.T) { PluginContext: pluginCtx, } - err := cdt.Decorator.CallResource(req.Context(), crr, nopCallResourceSender) + err := cdt.MiddlewareHandler.CallResource(req.Context(), crr, nopCallResourceSender) assert.NoError(t, err) // Cache service is never called cs.AssertCalls(t, "HandleResourceRequest", 0) diff --git a/pkg/services/pluginsintegration/clientmiddleware/clear_auth_headers_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/clear_auth_headers_middleware.go index 1ec57e09f39..7a942eb4661 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/clear_auth_headers_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/clear_auth_headers_middleware.go @@ -5,25 +5,22 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/contexthandler" ) -// NewClearAuthHeadersMiddleware creates a new plugins.ClientMiddleware +// NewClearAuthHeadersMiddleware creates a new backend.HandlerMiddleware // that will clear any outgoing HTTP headers that was part of the incoming // HTTP request and used when authenticating to Grafana. -func NewClearAuthHeadersMiddleware() plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func NewClearAuthHeadersMiddleware() backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &ClearAuthHeadersMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, + BaseHandler: backend.NewBaseHandler(next), } }) } type ClearAuthHeadersMiddleware struct { - baseMiddleware + backend.BaseHandler } func (m *ClearAuthHeadersMiddleware) clearHeaders(ctx context.Context, h backend.ForwardHTTPHeaders) { @@ -43,30 +40,30 @@ func (m *ClearAuthHeadersMiddleware) clearHeaders(ctx context.Context, h backend func (m *ClearAuthHeadersMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { if req == nil { - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } m.clearHeaders(ctx, req) - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } func (m *ClearAuthHeadersMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { if req == nil { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } m.clearHeaders(ctx, req) - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } func (m *ClearAuthHeadersMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { if req == nil { - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } m.clearHeaders(ctx, req) - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } diff --git a/pkg/services/pluginsintegration/clientmiddleware/clear_auth_headers_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/clear_auth_headers_middleware_test.go index 2aa709ff987..a02e3d3500d 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/clear_auth_headers_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/clear_auth_headers_middleware_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" @@ -23,9 +23,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { req.Header.Set(otherHeader, "test") t.Run("And requests are for a datasource", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()), ) pluginCtx := backend.PluginContext{ @@ -33,7 +33,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { } t.Run("Should not attach delete headers middleware when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -43,7 +43,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { }) t.Run("Should not attach delete headers middleware when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{otherHeader: {"test"}}, }, nopCallResourceSender) @@ -53,7 +53,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { }) t.Run("Should not attach delete headers middleware when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -64,9 +64,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { }) t.Run("And requests are for an app", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()), ) pluginCtx := backend.PluginContext{ @@ -74,7 +74,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { } t.Run("Should not attach delete headers middleware when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -84,7 +84,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { }) t.Run("Should not attach delete headers middleware when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{otherHeader: {"test"}}, }, nopCallResourceSender) @@ -94,7 +94,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { }) t.Run("Should not attach delete headers middleware when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -110,9 +110,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { require.NoError(t, err) t.Run("And requests are for a datasource", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()), ) req := req.WithContext(contexthandler.WithAuthHTTPHeaders(req.Context(), setting.NewCfg())) @@ -126,7 +126,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { } t.Run("Should attach delete headers middleware when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -137,7 +137,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { }) t.Run("Should attach delete headers middleware when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{otherHeader: {"test"}}, }, nopCallResourceSender) @@ -148,7 +148,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { }) t.Run("Should attach delete headers middleware when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -160,9 +160,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { }) t.Run("And requests are for an app", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()), ) req := req.WithContext(contexthandler.WithAuthHTTPHeaders(req.Context(), setting.NewCfg())) @@ -176,7 +176,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { } t.Run("Should attach delete headers middleware when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -187,7 +187,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { }) t.Run("Should attach delete headers middleware when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{otherHeader: {"test"}}, }, nopCallResourceSender) @@ -198,7 +198,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) { }) t.Run("Should attach delete headers middleware when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) diff --git a/pkg/services/pluginsintegration/clientmiddleware/contextual_logger_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/contextual_logger_middleware.go index 53325809c73..fbb6f7c23e7 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/contextual_logger_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/contextual_logger_middleware.go @@ -6,21 +6,20 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/plugins" ) -// NewContextualLoggerMiddleware creates a new plugins.ClientMiddleware that adds +// NewContextualLoggerMiddleware creates a new backend.HandlerMiddleware that adds // a contextual logger to the request context. -func NewContextualLoggerMiddleware() plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func NewContextualLoggerMiddleware() backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &ContextualLoggerMiddleware{ - next: next, + BaseHandler: backend.NewBaseHandler(next), } }) } type ContextualLoggerMiddleware struct { - next plugins.Client + backend.BaseHandler } // instrumentContext adds a contextual logger with plugin and request details to the given context. @@ -45,53 +44,53 @@ func instrumentContext(ctx context.Context, pCtx backend.PluginContext) context. func (m *ContextualLoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { ctx = instrumentContext(ctx, req.PluginContext) - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } func (m *ContextualLoggerMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { ctx = instrumentContext(ctx, req.PluginContext) - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } func (m *ContextualLoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { ctx = instrumentContext(ctx, req.PluginContext) - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } func (m *ContextualLoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) { ctx = instrumentContext(ctx, req.PluginContext) - return m.next.CollectMetrics(ctx, req) + return m.BaseHandler.CollectMetrics(ctx, req) } func (m *ContextualLoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) { ctx = instrumentContext(ctx, req.PluginContext) - return m.next.SubscribeStream(ctx, req) + return m.BaseHandler.SubscribeStream(ctx, req) } func (m *ContextualLoggerMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) { ctx = instrumentContext(ctx, req.PluginContext) - return m.next.PublishStream(ctx, req) + return m.BaseHandler.PublishStream(ctx, req) } func (m *ContextualLoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error { ctx = instrumentContext(ctx, req.PluginContext) - return m.next.RunStream(ctx, req, sender) + return m.BaseHandler.RunStream(ctx, req, sender) } // ValidateAdmission implements backend.AdmissionHandler. func (m *ContextualLoggerMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) { ctx = instrumentContext(ctx, req.PluginContext) - return m.next.ValidateAdmission(ctx, req) + return m.BaseHandler.ValidateAdmission(ctx, req) } // MutateAdmission implements backend.AdmissionHandler. func (m *ContextualLoggerMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) { ctx = instrumentContext(ctx, req.PluginContext) - return m.next.MutateAdmission(ctx, req) + return m.BaseHandler.MutateAdmission(ctx, req) } // ConvertObject implements backend.AdmissionHandler. func (m *ContextualLoggerMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) { ctx = instrumentContext(ctx, req.PluginContext) - return m.next.ConvertObjects(ctx, req) + return m.BaseHandler.ConvertObjects(ctx, req) } diff --git a/pkg/services/pluginsintegration/clientmiddleware/cookies_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/cookies_middleware.go index 73e1a1f3d78..fc1ba372ae5 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/cookies_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/cookies_middleware.go @@ -6,7 +6,6 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana/pkg/components/simplejson" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/util/proxyutil" @@ -14,22 +13,20 @@ import ( const cookieHeaderName = "Cookie" -// NewCookiesMiddleware creates a new plugins.ClientMiddleware that will -// forward incoming HTTP request Cookies to outgoing plugins.Client requests +// NewCookiesMiddleware creates a new backend.HandlerMiddleware that will +// forward incoming HTTP request Cookies to outgoing backend.Handler requests // if the datasource has enabled forwarding of cookies (keepCookies). -func NewCookiesMiddleware(skipCookiesNames []string) plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func NewCookiesMiddleware(skipCookiesNames []string) backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &CookiesMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, + BaseHandler: backend.NewBaseHandler(next), skipCookiesNames: skipCookiesNames, } }) } type CookiesMiddleware struct { - baseMiddleware + backend.BaseHandler skipCookiesNames []string } @@ -87,7 +84,7 @@ func (m *CookiesMiddleware) applyCookies(ctx context.Context, pCtx backend.Plugi func (m *CookiesMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { if req == nil { - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } err := m.applyCookies(ctx, req.PluginContext, req) @@ -95,12 +92,12 @@ func (m *CookiesMiddleware) QueryData(ctx context.Context, req *backend.QueryDat return nil, err } - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } func (m *CookiesMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { if req == nil { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } err := m.applyCookies(ctx, req.PluginContext, req) @@ -108,12 +105,12 @@ func (m *CookiesMiddleware) CallResource(ctx context.Context, req *backend.CallR return err } - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } func (m *CookiesMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { if req == nil { - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } err := m.applyCookies(ctx, req.PluginContext, req) @@ -121,5 +118,5 @@ func (m *CookiesMiddleware) CheckHealth(ctx context.Context, req *backend.CheckH return nil, err } - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } diff --git a/pkg/services/pluginsintegration/clientmiddleware/cookies_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/cookies_middleware_test.go index 41822d6a4ba..778363b4936 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/cookies_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/cookies_middleware_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/grafana/grafana/pkg/services/user" "github.com/stretchr/testify/require" ) @@ -28,9 +28,9 @@ func TestCookiesMiddleware(t *testing.T) { }) req.Header.Set(otherHeader, "test") - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})), ) jsonDataMap := map[string]any{} @@ -44,7 +44,7 @@ func TestCookiesMiddleware(t *testing.T) { } t.Run("Should not forward cookies when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -60,7 +60,7 @@ func TestCookiesMiddleware(t *testing.T) { Headers: map[string][]string{otherHeader: {"test"}}, } pReq.Headers[backend.CookiesHeaderName] = []string{req.Header.Get(backend.CookiesHeaderName)} - err = cdt.Decorator.CallResource(req.Context(), pReq, nopCallResourceSender) + err = cdt.MiddlewareHandler.CallResource(req.Context(), pReq, nopCallResourceSender) require.NoError(t, err) require.NotNil(t, cdt.CallResourceReq) require.Len(t, cdt.CallResourceReq.Headers, 1) @@ -68,7 +68,7 @@ func TestCookiesMiddleware(t *testing.T) { }) t.Run("Should not forward cookies when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -97,9 +97,9 @@ func TestCookiesMiddleware(t *testing.T) { req.Header.Set(otherHeader, "test") - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})), ) jsonDataMap := map[string]any{ @@ -115,7 +115,7 @@ func TestCookiesMiddleware(t *testing.T) { } t.Run("Should forward cookies when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -127,7 +127,7 @@ func TestCookiesMiddleware(t *testing.T) { }) t.Run("Should forward cookies when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{otherHeader: {"test"}}, }, nopCallResourceSender) @@ -140,7 +140,7 @@ func TestCookiesMiddleware(t *testing.T) { }) t.Run("Should forward cookies when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -166,9 +166,9 @@ func TestCookiesMiddleware(t *testing.T) { }) req.Header.Set(otherHeader, "test") - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})), ) pluginCtx := backend.PluginContext{ @@ -181,7 +181,7 @@ func TestCookiesMiddleware(t *testing.T) { Headers: map[string]string{otherHeader: "test"}, } pReq.Headers[backend.CookiesHeaderName] = req.Header.Get(backend.CookiesHeaderName) - _, err = cdt.Decorator.QueryData(req.Context(), pReq) + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), pReq) require.NoError(t, err) require.NotNil(t, cdt.QueryDataReq) require.Len(t, cdt.QueryDataReq.Headers, 1) @@ -194,7 +194,7 @@ func TestCookiesMiddleware(t *testing.T) { Headers: map[string][]string{otherHeader: {"test"}}, } pReq.Headers[backend.CookiesHeaderName] = []string{req.Header.Get(backend.CookiesHeaderName)} - err = cdt.Decorator.CallResource(req.Context(), pReq, nopCallResourceSender) + err = cdt.MiddlewareHandler.CallResource(req.Context(), pReq, nopCallResourceSender) require.NoError(t, err) require.NotNil(t, cdt.CallResourceReq) require.Len(t, cdt.CallResourceReq.Headers, 1) @@ -207,7 +207,7 @@ func TestCookiesMiddleware(t *testing.T) { Headers: map[string]string{otherHeader: "test"}, } pReq.Headers[backend.CookiesHeaderName] = req.Header.Get(backend.CookiesHeaderName) - _, err = cdt.Decorator.CheckHealth(req.Context(), pReq) + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), pReq) require.NoError(t, err) require.NotNil(t, cdt.CheckHealthReq) require.Len(t, cdt.CheckHealthReq.Headers, 1) diff --git a/pkg/services/pluginsintegration/clientmiddleware/forward_id_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/forward_id_middleware.go index 9e799759157..42764a7641f 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/forward_id_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/forward_id_middleware.go @@ -5,26 +5,23 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/contexthandler" ) const forwardIDHeaderName = "X-Grafana-Id" -// NewForwardIDMiddleware creates a new plugins.ClientMiddleware that will -// set grafana id header on outgoing plugins.Client requests -func NewForwardIDMiddleware() plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +// NewForwardIDMiddleware creates a new backend.HandlerMiddleware that will +// set grafana id header on outgoing backend.Handler requests +func NewForwardIDMiddleware() backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &ForwardIDMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, + BaseHandler: backend.NewBaseHandler(next), } }) } type ForwardIDMiddleware struct { - baseMiddleware + backend.BaseHandler } func (m *ForwardIDMiddleware) applyToken(ctx context.Context, pCtx backend.PluginContext, req backend.ForwardHTTPHeaders) error { @@ -43,7 +40,7 @@ func (m *ForwardIDMiddleware) applyToken(ctx context.Context, pCtx backend.Plugi func (m *ForwardIDMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { if req == nil { - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } err := m.applyToken(ctx, req.PluginContext, req) @@ -51,12 +48,12 @@ func (m *ForwardIDMiddleware) QueryData(ctx context.Context, req *backend.QueryD return nil, err } - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } func (m *ForwardIDMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { if req == nil { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } err := m.applyToken(ctx, req.PluginContext, req) @@ -64,12 +61,12 @@ func (m *ForwardIDMiddleware) CallResource(ctx context.Context, req *backend.Cal return err } - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } func (m *ForwardIDMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { if req == nil { - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } err := m.applyToken(ctx, req.PluginContext, req) @@ -77,5 +74,5 @@ func (m *ForwardIDMiddleware) CheckHealth(ctx context.Context, req *backend.Chec return nil, err } - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } diff --git a/pkg/services/pluginsintegration/clientmiddleware/forward_id_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/forward_id_middleware_test.go index 2972c612a92..bc8532e7f75 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/forward_id_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/forward_id_middleware_test.go @@ -6,9 +6,9 @@ import ( "testing" "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" "github.com/grafana/grafana/pkg/services/contexthandler/ctxkey" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" "github.com/grafana/grafana/pkg/services/user" @@ -21,14 +21,14 @@ func TestForwardIDMiddleware(t *testing.T) { } t.Run("Should set forwarded id header if present", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewForwardIDMiddleware())) + cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewForwardIDMiddleware())) ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{ Context: &web.Context{Req: &http.Request{}}, SignedInUser: &user.SignedInUser{IDToken: "some-token"}, }) - err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{ + err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{ PluginContext: pluginContext, }, nopCallResourceSender) require.NoError(t, err) @@ -37,14 +37,14 @@ func TestForwardIDMiddleware(t *testing.T) { }) t.Run("Should not set forwarded id header if not present", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewForwardIDMiddleware())) + cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewForwardIDMiddleware())) ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{ Context: &web.Context{Req: &http.Request{}}, SignedInUser: &user.SignedInUser{}, }) - err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{ + err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{ PluginContext: pluginContext, }, nopCallResourceSender) require.NoError(t, err) @@ -57,14 +57,14 @@ func TestForwardIDMiddleware(t *testing.T) { } t.Run("Should set forwarded id header to app plugin if present", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewForwardIDMiddleware())) + cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewForwardIDMiddleware())) ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{ Context: &web.Context{Req: &http.Request{}}, SignedInUser: &user.SignedInUser{IDToken: "some-token"}, }) - err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{ + err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{ PluginContext: pluginContext, }, nopCallResourceSender) require.NoError(t, err) diff --git a/pkg/services/pluginsintegration/clientmiddleware/grafana_request_id_header_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/grafana_request_id_header_middleware.go index c6c4a5947a6..9a23168c6f5 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/grafana_request_id_header_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/grafana_request_id_header_middleware.go @@ -13,7 +13,6 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/web" @@ -24,24 +23,22 @@ const GrafanaSignedRequestID = "X-Grafana-Signed-Request-Id" const XRealIPHeader = "X-Real-Ip" const GrafanaInternalRequest = "X-Grafana-Internal-Request" -// NewHostedGrafanaACHeaderMiddleware creates a new plugins.ClientMiddleware that will +// NewHostedGrafanaACHeaderMiddleware creates a new backend.HandlerMiddleware that will // generate a random request ID, sign it using internal key and populate X-Grafana-Request-ID with the request ID // and X-Grafana-Signed-Request-ID with signed request ID. We can then use this to verify that the request // is coming from hosted Grafana and is not an external request. This is used for IP range access control. -func NewHostedGrafanaACHeaderMiddleware(cfg *setting.Cfg) plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func NewHostedGrafanaACHeaderMiddleware(cfg *setting.Cfg) backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &HostedGrafanaACHeaderMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, - log: log.New("ip_header_middleware"), - cfg: cfg, + BaseHandler: backend.NewBaseHandler(next), + log: log.New("ip_header_middleware"), + cfg: cfg, } }) } type HostedGrafanaACHeaderMiddleware struct { - baseMiddleware + backend.BaseHandler log log.Logger cfg *setting.Cfg } @@ -120,30 +117,30 @@ func GetGrafanaRequestIDHeaders(req *http.Request, cfg *setting.Cfg, logger log. func (m *HostedGrafanaACHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { if req == nil { - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req) - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } func (m *HostedGrafanaACHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { if req == nil { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req) - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } func (m *HostedGrafanaACHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { if req == nil { - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req) - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } diff --git a/pkg/services/pluginsintegration/clientmiddleware/grafana_request_id_header_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/grafana_request_id_header_middleware_test.go index 3c389edea1d..01e398f4004 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/grafana_request_id_header_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/grafana_request_id_header_middleware_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/grafana/grafana/pkg/services/contexthandler/ctxkey" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" "github.com/grafana/grafana/pkg/services/user" @@ -26,7 +26,7 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) { allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"} cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL} cfg.IPRangeACSecretKey = "secret" - cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg))) + cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg))) ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{ Context: &web.Context{Req: &http.Request{ @@ -35,7 +35,7 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) { SignedInUser: &user.SignedInUser{}, }) - err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{ + err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{ PluginContext: backend.PluginContext{ DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{ URL: "https://logs.grafana.net", @@ -68,14 +68,14 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) { allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"} cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL} cfg.IPRangeACSecretKey = "secret" - cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg))) + cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg))) ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{ Context: &web.Context{Req: &http.Request{}}, SignedInUser: &user.SignedInUser{}, }) - err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{ + err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{ PluginContext: backend.PluginContext{ DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{ URL: "https://logs.not-grafana.net", @@ -93,14 +93,14 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) { allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"} cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL} cfg.IPRangeACSecretKey = "secret" - cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg))) + cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg))) ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{ Context: &web.Context{Req: &http.Request{}}, SignedInUser: &user.SignedInUser{}, }) - err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{ + err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{ PluginContext: backend.PluginContext{ DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{ URL: "https://logs.grafana.net/abc/../some/path", @@ -118,14 +118,14 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) { allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"} cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL} cfg.IPRangeACSecretKey = "secret" - cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg))) + cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg))) ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{ Context: &web.Context{Req: &http.Request{}}, SignedInUser: &user.SignedInUser{}, }) - err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{ + err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{ PluginContext: backend.PluginContext{ DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{ URL: "https://logs.grafana.net", diff --git a/pkg/services/pluginsintegration/clientmiddleware/httpclient_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/httpclient_middleware.go index 913ad4e0bf5..723c9788944 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/httpclient_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/httpclient_middleware.go @@ -7,26 +7,23 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" - "github.com/grafana/grafana/pkg/plugins" ngalertmodels "github.com/grafana/grafana/pkg/services/ngalert/models" ) const forwardPluginRequestHTTPHeaders = "forward-plugin-request-http-headers" -// NewHTTPClientMiddleware creates a new plugins.ClientMiddleware +// NewHTTPClientMiddleware creates a new backend.HandlerMiddleware // that will forward plugin request headers as outgoing HTTP headers. -func NewHTTPClientMiddleware() plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func NewHTTPClientMiddleware() backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &HTTPClientMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, + BaseHandler: backend.NewBaseHandler(next), } }) } type HTTPClientMiddleware struct { - baseMiddleware + backend.BaseHandler } func (m *HTTPClientMiddleware) applyHeaders(ctx context.Context, pReq any) context.Context { @@ -69,30 +66,30 @@ func (m *HTTPClientMiddleware) applyHeaders(ctx context.Context, pReq any) conte func (m *HTTPClientMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { if req == nil { - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } ctx = m.applyHeaders(ctx, req) - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } func (m *HTTPClientMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { if req == nil { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } ctx = m.applyHeaders(ctx, req) - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } func (m *HTTPClientMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { if req == nil { - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } ctx = m.applyHeaders(ctx, req) - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } diff --git a/pkg/services/pluginsintegration/clientmiddleware/httpclient_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/httpclient_middleware_test.go index 58f3faf3c99..a61046b9150 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/httpclient_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/httpclient_middleware_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" ngalertmodels "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/util/proxyutil" @@ -23,9 +23,9 @@ func TestHTTPClientMiddleware(t *testing.T) { require.NoError(t, err) t.Run("And requests are for a datasource", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewHTTPClientMiddleware()), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewHTTPClientMiddleware()), ) pluginCtx := backend.PluginContext{ @@ -33,7 +33,7 @@ func TestHTTPClientMiddleware(t *testing.T) { } t.Run("Should not forward headers when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "val"}, }) @@ -53,7 +53,7 @@ func TestHTTPClientMiddleware(t *testing.T) { }) t.Run("Should not forward headers when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{otherHeader: {"val"}}, }, nopCallResourceSender) @@ -73,7 +73,7 @@ func TestHTTPClientMiddleware(t *testing.T) { }) t.Run("Should not forward headers when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "val"}, }) @@ -94,9 +94,9 @@ func TestHTTPClientMiddleware(t *testing.T) { }) t.Run("And requests are for an app", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewHTTPClientMiddleware()), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewHTTPClientMiddleware()), ) pluginCtx := backend.PluginContext{ @@ -104,7 +104,7 @@ func TestHTTPClientMiddleware(t *testing.T) { } t.Run("Should not forward headers when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -124,7 +124,7 @@ func TestHTTPClientMiddleware(t *testing.T) { }) t.Run("Should not forward headers when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{}, }, nopCallResourceSender) @@ -144,7 +144,7 @@ func TestHTTPClientMiddleware(t *testing.T) { }) t.Run("Should not forward headers when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -184,9 +184,9 @@ func TestHTTPClientMiddleware(t *testing.T) { } t.Run("And requests are for a datasource", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewHTTPClientMiddleware()), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewHTTPClientMiddleware()), ) pluginCtx := backend.PluginContext{ @@ -194,7 +194,7 @@ func TestHTTPClientMiddleware(t *testing.T) { } t.Run("Should forward headers when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: headers, }) @@ -222,7 +222,7 @@ func TestHTTPClientMiddleware(t *testing.T) { }) t.Run("Should forward headers when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: crHeaders, }, nopCallResourceSender) @@ -250,7 +250,7 @@ func TestHTTPClientMiddleware(t *testing.T) { }) t.Run("Should forward headers when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: headers, }) @@ -278,7 +278,7 @@ func TestHTTPClientMiddleware(t *testing.T) { }) t.Run("Should not overwrite an existing header", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: headers, }) diff --git a/pkg/services/pluginsintegration/clientmiddleware/logger_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/logger_middleware.go index 526c13b95fa..ab1eb9f751a 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/logger_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/logger_middleware.go @@ -7,21 +7,18 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/instrumentationutils" plog "github.com/grafana/grafana/pkg/plugins/log" "github.com/grafana/grafana/pkg/plugins/manager/registry" "github.com/grafana/grafana/pkg/plugins/pluginrequestmeta" ) -// NewLoggerMiddleware creates a new plugins.ClientMiddleware that will +// NewLoggerMiddleware creates a new backend.HandlerMiddleware that will // log requests. -func NewLoggerMiddleware(logger plog.Logger, pluginRegistry registry.Service) plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func NewLoggerMiddleware(logger plog.Logger, pluginRegistry registry.Service) backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &LoggerMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, + BaseHandler: backend.NewBaseHandler(next), logger: logger, pluginRegistry: pluginRegistry, } @@ -29,7 +26,7 @@ func NewLoggerMiddleware(logger plog.Logger, pluginRegistry registry.Service) pl } type LoggerMiddleware struct { - baseMiddleware + backend.BaseHandler logger plog.Logger pluginRegistry registry.Service } @@ -77,13 +74,13 @@ func (m *LoggerMiddleware) logRequest(ctx context.Context, pCtx backend.PluginCo func (m *LoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { if req == nil { - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } var resp *backend.QueryDataResponse err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.QueryData(ctx, req) + resp, innerErr = m.BaseHandler.QueryData(ctx, req) if innerErr != nil { return instrumentationutils.RequestStatusFromError(innerErr), innerErr @@ -110,11 +107,11 @@ func (m *LoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryData func (m *LoggerMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { if req == nil { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { - innerErr := m.next.CallResource(ctx, req, sender) + innerErr := m.BaseHandler.CallResource(ctx, req, sender) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) @@ -123,13 +120,13 @@ func (m *LoggerMiddleware) CallResource(ctx context.Context, req *backend.CallRe func (m *LoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { if req == nil { - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } var resp *backend.CheckHealthResult err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.CheckHealth(ctx, req) + resp, innerErr = m.BaseHandler.CheckHealth(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) @@ -138,13 +135,13 @@ func (m *LoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHe func (m *LoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) { if req == nil { - return m.next.CollectMetrics(ctx, req) + return m.BaseHandler.CollectMetrics(ctx, req) } var resp *backend.CollectMetricsResult err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.CollectMetrics(ctx, req) + resp, innerErr = m.BaseHandler.CollectMetrics(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) @@ -153,13 +150,13 @@ func (m *LoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.Coll func (m *LoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) { if req == nil { - return m.next.SubscribeStream(ctx, req) + return m.BaseHandler.SubscribeStream(ctx, req) } var resp *backend.SubscribeStreamResponse err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.SubscribeStream(ctx, req) + resp, innerErr = m.BaseHandler.SubscribeStream(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) @@ -168,13 +165,13 @@ func (m *LoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.Sub func (m *LoggerMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) { if req == nil { - return m.next.PublishStream(ctx, req) + return m.BaseHandler.PublishStream(ctx, req) } var resp *backend.PublishStreamResponse err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.PublishStream(ctx, req) + resp, innerErr = m.BaseHandler.PublishStream(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) @@ -183,11 +180,11 @@ func (m *LoggerMiddleware) PublishStream(ctx context.Context, req *backend.Publi func (m *LoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error { if req == nil { - return m.next.RunStream(ctx, req, sender) + return m.BaseHandler.RunStream(ctx, req, sender) } err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { - innerErr := m.next.RunStream(ctx, req, sender) + innerErr := m.BaseHandler.RunStream(ctx, req, sender) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) @@ -196,13 +193,13 @@ func (m *LoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStream func (m *LoggerMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) { if req == nil { - return m.next.ValidateAdmission(ctx, req) + return m.BaseHandler.ValidateAdmission(ctx, req) } var resp *backend.ValidationResponse err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.ValidateAdmission(ctx, req) + resp, innerErr = m.BaseHandler.ValidateAdmission(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) @@ -211,13 +208,13 @@ func (m *LoggerMiddleware) ValidateAdmission(ctx context.Context, req *backend.A func (m *LoggerMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) { if req == nil { - return m.next.MutateAdmission(ctx, req) + return m.BaseHandler.MutateAdmission(ctx, req) } var resp *backend.MutationResponse err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.MutateAdmission(ctx, req) + resp, innerErr = m.BaseHandler.MutateAdmission(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) @@ -226,13 +223,13 @@ func (m *LoggerMiddleware) MutateAdmission(ctx context.Context, req *backend.Adm func (m *LoggerMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) { if req == nil { - return m.next.ConvertObjects(ctx, req) + return m.BaseHandler.ConvertObjects(ctx, req) } var resp *backend.ConversionResponse err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.ConvertObjects(ctx, req) + resp, innerErr = m.BaseHandler.ConvertObjects(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) diff --git a/pkg/services/pluginsintegration/clientmiddleware/metrics_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/metrics_middleware.go index a93c0a13a2a..29e7b1ec998 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/metrics_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/metrics_middleware.go @@ -25,7 +25,7 @@ type pluginMetrics struct { // MetricsMiddleware is a middleware that instruments plugin requests. // It tracks requests count, duration and size as prometheus metrics. type MetricsMiddleware struct { - baseMiddleware + backend.BaseHandler pluginMetrics pluginRegistry registry.Service } @@ -75,12 +75,10 @@ func newMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry r } // NewMetricsMiddleware returns a new MetricsMiddleware. -func NewMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry registry.Service) plugins.ClientMiddleware { +func NewMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry registry.Service) backend.HandlerMiddleware { imw := newMetricsMiddleware(promRegisterer, pluginRegistry) - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { - imw.baseMiddleware = baseMiddleware{ - next: next, - } + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { + imw.BaseHandler = backend.NewBaseHandler(next) return imw }) } @@ -154,7 +152,7 @@ func (m *MetricsMiddleware) QueryData(ctx context.Context, req *backend.QueryDat var resp *backend.QueryDataResponse err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.QueryData(ctx, req) + resp, innerErr = m.BaseHandler.QueryData(ctx, req) return instrumentationutils.RequestStatusFromQueryDataResponse(resp, innerErr), innerErr }) @@ -166,7 +164,7 @@ func (m *MetricsMiddleware) CallResource(ctx context.Context, req *backend.CallR return err } return m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { - innerErr := m.next.CallResource(ctx, req, sender) + innerErr := m.BaseHandler.CallResource(ctx, req, sender) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) } @@ -175,7 +173,7 @@ func (m *MetricsMiddleware) CheckHealth(ctx context.Context, req *backend.CheckH var resp *backend.CheckHealthResult err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.CheckHealth(ctx, req) + resp, innerErr = m.BaseHandler.CheckHealth(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) @@ -186,7 +184,7 @@ func (m *MetricsMiddleware) CollectMetrics(ctx context.Context, req *backend.Col var resp *backend.CollectMetricsResult err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.CollectMetrics(ctx, req) + resp, innerErr = m.BaseHandler.CollectMetrics(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) return resp, err @@ -196,7 +194,7 @@ func (m *MetricsMiddleware) SubscribeStream(ctx context.Context, req *backend.Su var resp *backend.SubscribeStreamResponse err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.SubscribeStream(ctx, req) + resp, innerErr = m.BaseHandler.SubscribeStream(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) return resp, err @@ -206,7 +204,7 @@ func (m *MetricsMiddleware) PublishStream(ctx context.Context, req *backend.Publ var resp *backend.PublishStreamResponse err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.PublishStream(ctx, req) + resp, innerErr = m.BaseHandler.PublishStream(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) return resp, err @@ -214,7 +212,7 @@ func (m *MetricsMiddleware) PublishStream(ctx context.Context, req *backend.Publ func (m *MetricsMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error { err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { - innerErr := m.next.RunStream(ctx, req, sender) + innerErr := m.BaseHandler.RunStream(ctx, req, sender) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) return err @@ -224,7 +222,7 @@ func (m *MetricsMiddleware) ValidateAdmission(ctx context.Context, req *backend. var resp *backend.ValidationResponse err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.ValidateAdmission(ctx, req) + resp, innerErr = m.BaseHandler.ValidateAdmission(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) @@ -235,7 +233,7 @@ func (m *MetricsMiddleware) MutateAdmission(ctx context.Context, req *backend.Ad var resp *backend.MutationResponse err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.MutateAdmission(ctx, req) + resp, innerErr = m.BaseHandler.MutateAdmission(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) @@ -246,7 +244,7 @@ func (m *MetricsMiddleware) ConvertObjects(ctx context.Context, req *backend.Con var resp *backend.ConversionResponse err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) { var innerErr error - resp, innerErr = m.next.ConvertObjects(ctx, req) + resp, innerErr = m.BaseHandler.ConvertObjects(ctx, req) return instrumentationutils.RequestStatusFromError(innerErr), innerErr }) diff --git a/pkg/services/pluginsintegration/clientmiddleware/metrics_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/metrics_middleware_test.go index 40c26cef09a..1af03e7af79 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/metrics_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/metrics_middleware_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/testutil" dto "github.com/prometheus/client_model/go" @@ -15,7 +16,6 @@ import ( "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/backendplugin" "github.com/grafana/grafana/pkg/plugins/instrumentationutils" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" "github.com/grafana/grafana/pkg/plugins/manager/fakes" "github.com/grafana/grafana/pkg/plugins/pluginrequestmeta" ) @@ -34,36 +34,36 @@ func TestInstrumentationMiddleware(t *testing.T) { t.Run("should instrument requests", func(t *testing.T) { for _, tc := range []struct { expEndpoint backend.Endpoint - fn func(cdt *clienttest.ClientDecoratorTest) error + fn func(cdt *handlertest.HandlerMiddlewareTest) error shouldInstrumentRequestSize bool }{ { expEndpoint: backend.EndpointCheckHealth, - fn: func(cdt *clienttest.ClientDecoratorTest) error { - _, err := cdt.Decorator.CheckHealth(context.Background(), &backend.CheckHealthRequest{PluginContext: pCtx}) + fn: func(cdt *handlertest.HandlerMiddlewareTest) error { + _, err := cdt.MiddlewareHandler.CheckHealth(context.Background(), &backend.CheckHealthRequest{PluginContext: pCtx}) return err }, shouldInstrumentRequestSize: false, }, { expEndpoint: backend.EndpointCallResource, - fn: func(cdt *clienttest.ClientDecoratorTest) error { - return cdt.Decorator.CallResource(context.Background(), &backend.CallResourceRequest{PluginContext: pCtx}, nopCallResourceSender) + fn: func(cdt *handlertest.HandlerMiddlewareTest) error { + return cdt.MiddlewareHandler.CallResource(context.Background(), &backend.CallResourceRequest{PluginContext: pCtx}, nopCallResourceSender) }, shouldInstrumentRequestSize: true, }, { expEndpoint: backend.EndpointQueryData, - fn: func(cdt *clienttest.ClientDecoratorTest) error { - _, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx}) + fn: func(cdt *handlertest.HandlerMiddlewareTest) error { + _, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx}) return err }, shouldInstrumentRequestSize: true, }, { expEndpoint: backend.EndpointCollectMetrics, - fn: func(cdt *clienttest.ClientDecoratorTest) error { - _, err := cdt.Decorator.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{PluginContext: pCtx}) + fn: func(cdt *handlertest.HandlerMiddlewareTest) error { + _, err := cdt.MiddlewareHandler.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{PluginContext: pCtx}) return err }, shouldInstrumentRequestSize: false, @@ -77,9 +77,9 @@ func TestInstrumentationMiddleware(t *testing.T) { })) mw := newMetricsMiddleware(promRegistry, pluginsRegistry) - cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares( - plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { - mw.next = next + cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares( + backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { + mw.BaseHandler = backend.NewBaseHandler(next) return mw }), )) @@ -154,10 +154,10 @@ func TestInstrumentationMiddlewareStatusSource(t *testing.T) { JSONData: plugins.JSONData{ID: pluginID, Backend: true}, })) metricsMw := newMetricsMiddleware(promRegistry, pluginsRegistry) - cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares( + cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares( NewPluginRequestMetaMiddleware(), - plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { - metricsMw.next = next + backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { + metricsMw.BaseHandler = backend.NewBaseHandler(next) return metricsMw }), NewStatusSourceMiddleware(), @@ -166,10 +166,10 @@ func TestInstrumentationMiddlewareStatusSource(t *testing.T) { t.Run("Metrics", func(t *testing.T) { metricsMw.pluginMetrics.pluginRequestCounter.Reset() - cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { + cdt.TestHandler.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { return &backend.QueryDataResponse{Responses: map[string]backend.DataResponse{"A": downstreamErrorResponse}}, nil } - _, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx}) + _, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx}) require.NoError(t, err) counter, err := metricsMw.pluginMetrics.pluginRequestCounter.GetMetricWith(newLabels( queryDataErrorCounterLabels, @@ -235,12 +235,12 @@ func TestInstrumentationMiddlewareStatusSource(t *testing.T) { cdt.QueryDataCtx = nil cdt.QueryDataReq = nil }) - cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { + cdt.TestHandler.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { cdt.QueryDataCtx = ctx cdt.QueryDataReq = req return &backend.QueryDataResponse{Responses: tc.responses}, nil } - _, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx}) + _, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx}) require.NoError(t, err) ctxStatusSource := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx) require.Equal(t, tc.expStatusSource, ctxStatusSource) diff --git a/pkg/services/pluginsintegration/clientmiddleware/oauthtoken_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/oauthtoken_middleware.go index b37a6f88e95..dcf59a50714 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/oauthtoken_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/oauthtoken_middleware.go @@ -7,28 +7,25 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana/pkg/components/simplejson" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/oauthtoken" ) -// NewOAuthTokenMiddleware creates a new plugins.ClientMiddleware that will -// set OAuth token headers on outgoing plugins.Client requests if the +// NewOAuthTokenMiddleware creates a new backend.HandlerMiddleware that will +// set OAuth token headers on outgoing backend.Handler requests if the // datasource has enabled Forward OAuth Identity (oauthPassThru). -func NewOAuthTokenMiddleware(oAuthTokenService oauthtoken.OAuthTokenService) plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func NewOAuthTokenMiddleware(oAuthTokenService oauthtoken.OAuthTokenService) backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &OAuthTokenMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, + BaseHandler: backend.NewBaseHandler(next), oAuthTokenService: oAuthTokenService, } }) } type OAuthTokenMiddleware struct { - baseMiddleware + backend.BaseHandler oAuthTokenService oauthtoken.OAuthTokenService } @@ -87,7 +84,7 @@ func (m *OAuthTokenMiddleware) applyToken(ctx context.Context, pCtx backend.Plug func (m *OAuthTokenMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { if req == nil { - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } err := m.applyToken(ctx, req.PluginContext, req) @@ -95,12 +92,12 @@ func (m *OAuthTokenMiddleware) QueryData(ctx context.Context, req *backend.Query return nil, err } - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } func (m *OAuthTokenMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { if req == nil { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } err := m.applyToken(ctx, req.PluginContext, req) @@ -108,12 +105,12 @@ func (m *OAuthTokenMiddleware) CallResource(ctx context.Context, req *backend.Ca return err } - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } func (m *OAuthTokenMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { if req == nil { - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } err := m.applyToken(ctx, req.PluginContext, req) @@ -121,5 +118,5 @@ func (m *OAuthTokenMiddleware) CheckHealth(ctx context.Context, req *backend.Che return nil, err } - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } diff --git a/pkg/services/pluginsintegration/clientmiddleware/oauthtoken_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/oauthtoken_middleware_test.go index 95e0a4212e2..abbf7be4813 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/oauthtoken_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/oauthtoken_middleware_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/grafana/grafana/pkg/services/oauthtoken/oauthtokentest" "github.com/grafana/grafana/pkg/services/user" "github.com/stretchr/testify/require" @@ -23,9 +23,9 @@ func TestOAuthTokenMiddleware(t *testing.T) { req.Header.Set(otherHeader, "test") oAuthTokenService := &oauthtokentest.Service{} - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)), ) jsonDataMap := map[string]any{} @@ -39,7 +39,7 @@ func TestOAuthTokenMiddleware(t *testing.T) { } t.Run("Should not forward OAuth Identity when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -50,7 +50,7 @@ func TestOAuthTokenMiddleware(t *testing.T) { }) t.Run("Should not forward OAuth Identity when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{otherHeader: {"test"}}, }, nopCallResourceSender) @@ -61,7 +61,7 @@ func TestOAuthTokenMiddleware(t *testing.T) { }) t.Run("Should not forward OAuth Identity when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -86,9 +86,9 @@ func TestOAuthTokenMiddleware(t *testing.T) { oAuthTokenService := &oauthtokentest.Service{ Token: token, } - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{}), - clienttest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)), + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{}), + handlertest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)), ) jsonDataMap := map[string]any{ @@ -104,7 +104,7 @@ func TestOAuthTokenMiddleware(t *testing.T) { } t.Run("Should forward OAuth Identity when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) @@ -117,7 +117,7 @@ func TestOAuthTokenMiddleware(t *testing.T) { }) t.Run("Should forward OAuth Identity when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{otherHeader: {"test"}}, }, nopCallResourceSender) @@ -132,7 +132,7 @@ func TestOAuthTokenMiddleware(t *testing.T) { }) t.Run("Should forward OAuth Identity when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{otherHeader: "test"}, }) diff --git a/pkg/services/pluginsintegration/clientmiddleware/plugin_request_meta_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/plugin_request_meta_middleware.go index 6536df9ee12..d24e5dc1472 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/plugin_request_meta_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/plugin_request_meta_middleware.go @@ -5,24 +5,23 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/pluginrequestmeta" ) -// NewPluginRequestMetaMiddleware returns a new plugins.ClientMiddleware that sets up the default +// NewPluginRequestMetaMiddleware returns a new backend.HandlerMiddleware that sets up the default // values for the plugin request meta in the context.Context. All middlewares that are executed // after this one are be able to access plugin request meta via the pluginrequestmeta package. -func NewPluginRequestMetaMiddleware() plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func NewPluginRequestMetaMiddleware() backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &PluginRequestMetaMiddleware{ - next: next, + BaseHandler: backend.NewBaseHandler(next), defaultStatusSource: pluginrequestmeta.DefaultStatusSource, } }) } type PluginRequestMetaMiddleware struct { - next plugins.Client + backend.BaseHandler defaultStatusSource pluginrequestmeta.StatusSource } @@ -35,53 +34,53 @@ func (m *PluginRequestMetaMiddleware) withDefaultPluginRequestMeta(ctx context.C func (m *PluginRequestMetaMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { ctx = m.withDefaultPluginRequestMeta(ctx) - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } func (m *PluginRequestMetaMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { ctx = m.withDefaultPluginRequestMeta(ctx) - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } func (m *PluginRequestMetaMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { ctx = m.withDefaultPluginRequestMeta(ctx) - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } func (m *PluginRequestMetaMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) { ctx = m.withDefaultPluginRequestMeta(ctx) - return m.next.CollectMetrics(ctx, req) + return m.BaseHandler.CollectMetrics(ctx, req) } func (m *PluginRequestMetaMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) { ctx = m.withDefaultPluginRequestMeta(ctx) - return m.next.SubscribeStream(ctx, req) + return m.BaseHandler.SubscribeStream(ctx, req) } func (m *PluginRequestMetaMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) { ctx = m.withDefaultPluginRequestMeta(ctx) - return m.next.PublishStream(ctx, req) + return m.BaseHandler.PublishStream(ctx, req) } func (m *PluginRequestMetaMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error { ctx = m.withDefaultPluginRequestMeta(ctx) - return m.next.RunStream(ctx, req, sender) + return m.BaseHandler.RunStream(ctx, req, sender) } // ValidateAdmission implements backend.AdmissionHandler. func (m *PluginRequestMetaMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) { ctx = m.withDefaultPluginRequestMeta(ctx) - return m.next.ValidateAdmission(ctx, req) + return m.BaseHandler.ValidateAdmission(ctx, req) } // MutateAdmission implements backend.AdmissionHandler. func (m *PluginRequestMetaMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) { ctx = m.withDefaultPluginRequestMeta(ctx) - return m.next.MutateAdmission(ctx, req) + return m.BaseHandler.MutateAdmission(ctx, req) } // ConvertObject implements backend.AdmissionHandler. func (m *PluginRequestMetaMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) { ctx = m.withDefaultPluginRequestMeta(ctx) - return m.next.ConvertObjects(ctx, req) + return m.BaseHandler.ConvertObjects(ctx, req) } diff --git a/pkg/services/pluginsintegration/clientmiddleware/plugin_request_meta_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/plugin_request_meta_middleware_test.go index 79adb858313..b87fcfb84d5 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/plugin_request_meta_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/plugin_request_meta_middleware_test.go @@ -5,34 +5,33 @@ import ( "testing" "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/plugins" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" "github.com/grafana/grafana/pkg/plugins/pluginrequestmeta" ) func TestPluginRequestMetaMiddleware(t *testing.T) { t.Run("default", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithMiddlewares(NewPluginRequestMetaMiddleware()), + cdt := handlertest.NewHandlerMiddlewareTest(t, + handlertest.WithMiddlewares(NewPluginRequestMetaMiddleware()), ) - _, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{}) + _, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{}) require.NoError(t, err) ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx) require.Equal(t, pluginrequestmeta.StatusSourcePlugin, ss) }) t.Run("other value", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithMiddlewares(plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { + cdt := handlertest.NewHandlerMiddlewareTest(t, + handlertest.WithMiddlewares(backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &PluginRequestMetaMiddleware{ - next: next, + BaseHandler: backend.NewBaseHandler(next), defaultStatusSource: "test", } })), ) - _, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{}) + _, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{}) require.NoError(t, err) ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx) require.Equal(t, pluginrequestmeta.StatusSource("test"), ss) diff --git a/pkg/services/pluginsintegration/clientmiddleware/resource_response_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/resource_response_middleware.go deleted file mode 100644 index b000a549656..00000000000 --- a/pkg/services/pluginsintegration/clientmiddleware/resource_response_middleware.go +++ /dev/null @@ -1,52 +0,0 @@ -package clientmiddleware - -import ( - "context" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - - "github.com/grafana/grafana/pkg/plugins" - "github.com/grafana/grafana/pkg/util/proxyutil" -) - -// NewResourceResponseMiddleware creates a new plugins.ClientMiddleware -// that will enforce HTTP header rules for backend.CallResourceResponse's. -func NewResourceResponseMiddleware() plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { - return &ResourceResponseMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, - } - }) -} - -type ResourceResponseMiddleware struct { - baseMiddleware -} - -func (m *ResourceResponseMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - return m.next.QueryData(ctx, req) -} - -func (m *ResourceResponseMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { - if req == nil || sender == nil { - return m.next.CallResource(ctx, req, sender) - } - - processedStreams := 0 - wrappedSender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error { - if processedStreams == 0 { - if res.Headers == nil { - res.Headers = map[string][]string{} - } - - proxyutil.SetProxyResponseHeaders(res.Headers) - } - - processedStreams++ - return sender.Send(res) - }) - - return m.next.CallResource(ctx, req, wrappedSender) -} diff --git a/pkg/services/pluginsintegration/clientmiddleware/resource_response_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/resource_response_middleware_test.go deleted file mode 100644 index 905977b32a4..00000000000 --- a/pkg/services/pluginsintegration/clientmiddleware/resource_response_middleware_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package clientmiddleware - -import ( - "context" - "net/http" - "testing" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" - "github.com/stretchr/testify/require" -) - -func TestResourceResponseMiddleware(t *testing.T) { - t.Run("Should set proxy response headers when calling CallResource", func(t *testing.T) { - crResp := &backend.CallResourceResponse{ - Status: http.StatusOK, - Headers: map[string][]string{ - "X-Custom": {"Should not be deleted"}, - }, - } - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithMiddlewares(NewResourceResponseMiddleware()), - clienttest.WithResourceResponses([]*backend.CallResourceResponse{crResp}), - ) - - var sentResponse *backend.CallResourceResponse - sender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error { - sentResponse = res - return nil - }) - - err := cdt.Decorator.CallResource(context.Background(), &backend.CallResourceRequest{ - PluginContext: backend.PluginContext{}, - }, sender) - require.NoError(t, err) - - require.NotNil(t, sentResponse) - require.Equal(t, "sandbox", sentResponse.Headers["Content-Security-Policy"][0]) - require.Equal(t, "Should not be deleted", sentResponse.Headers["X-Custom"][0]) - }) -} diff --git a/pkg/services/pluginsintegration/clientmiddleware/status_source_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/status_source_middleware.go index 5cd88c03aa6..d9af8df3887 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/status_source_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/status_source_middleware.go @@ -6,30 +6,27 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/pluginrequestmeta" ) -// NewStatusSourceMiddleware returns a new plugins.ClientMiddleware that sets the status source in the +// NewStatusSourceMiddleware returns a new backend.HandlerMiddleware that sets the status source in the // plugin request meta stored in the context.Context, according to the query data responses returned by QueryError. // If at least one query data response has a "downstream" status source and there isn't one with a "plugin" status source, // the plugin request meta in the context is set to "downstream". -func NewStatusSourceMiddleware() plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func NewStatusSourceMiddleware() backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &StatusSourceMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, + BaseHandler: backend.NewBaseHandler(next), } }) } type StatusSourceMiddleware struct { - baseMiddleware + backend.BaseHandler } func (m *StatusSourceMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { - resp, err := m.next.QueryData(ctx, req) + resp, err := m.BaseHandler.QueryData(ctx, req) if resp == nil || len(resp.Responses) == 0 { return resp, err } diff --git a/pkg/services/pluginsintegration/clientmiddleware/status_source_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/status_source_middleware_test.go index 88d5e7f0534..c3544d4e9df 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/status_source_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/status_source_middleware_test.go @@ -6,9 +6,9 @@ import ( "testing" "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" "github.com/grafana/grafana/pkg/plugins/pluginrequestmeta" ) @@ -68,18 +68,18 @@ func TestStatusSourceMiddleware(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithMiddlewares( + cdt := handlertest.NewHandlerMiddlewareTest(t, + handlertest.WithMiddlewares( NewPluginRequestMetaMiddleware(), NewStatusSourceMiddleware(), ), ) - cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { + cdt.TestHandler.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { cdt.QueryDataCtx = ctx return tc.queryDataResponse, nil } - _, _ = cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{}) + _, _ = cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{}) ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx) require.Equal(t, tc.expStatusSource, ss) diff --git a/pkg/services/pluginsintegration/clientmiddleware/testing.go b/pkg/services/pluginsintegration/clientmiddleware/testing.go index 391783cc0ef..0409fe9333b 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/testing.go +++ b/pkg/services/pluginsintegration/clientmiddleware/testing.go @@ -1,6 +1,31 @@ package clientmiddleware -import "github.com/grafana/grafana-plugin-sdk-go/backend" +import ( + "net/http" + "net/http/httptest" + + "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" + "github.com/grafana/grafana/pkg/services/contexthandler/ctxkey" + contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" + "github.com/grafana/grafana/pkg/services/user" + "github.com/grafana/grafana/pkg/web" +) + +func WithReqContext(req *http.Request, user *user.SignedInUser) handlertest.HandlerMiddlewareTestOption { + return handlertest.HandlerMiddlewareTestOption(func(cdt *handlertest.HandlerMiddlewareTest) { + reqContext := &contextmodel.ReqContext{ + Context: &web.Context{ + Req: req, + Resp: web.NewResponseWriter(req.Method, httptest.NewRecorder()), + }, + SignedInUser: user, + } + + ctx := ctxkey.Set(req.Context(), reqContext) + *req = *req.WithContext(ctx) + }) +} var nopCallResourceSender = backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error { return nil diff --git a/pkg/services/pluginsintegration/clientmiddleware/tracing_header_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/tracing_header_middleware.go index 30f9b47033a..035ae7f48cb 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/tracing_header_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/tracing_header_middleware.go @@ -5,28 +5,25 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/query" ) -// NewTracingHeaderMiddleware creates a new plugins.ClientMiddleware that will -// populate useful tracing headers on outgoing plugins.Client and HTTP +// NewTracingHeaderMiddleware creates a new backend.HandlerMiddleware that will +// populate useful tracing headers on outgoing backend.Handler and HTTP // requests. // Tracing headers are X-Datasource-Uid, X-Dashboard-Uid, // X-Panel-Id, X-Grafana-Org-Id. -func NewTracingHeaderMiddleware() plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func NewTracingHeaderMiddleware() backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &TracingHeaderMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, + BaseHandler: backend.NewBaseHandler(next), } }) } type TracingHeaderMiddleware struct { - baseMiddleware + backend.BaseHandler } func (m *TracingHeaderMiddleware) applyHeaders(ctx context.Context, req backend.ForwardHTTPHeaders) { @@ -49,22 +46,22 @@ func (m *TracingHeaderMiddleware) applyHeaders(ctx context.Context, req backend. func (m *TracingHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { if req == nil { - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } m.applyHeaders(ctx, req) - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } func (m *TracingHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } func (m *TracingHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { if req == nil { - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } m.applyHeaders(ctx, req) - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } diff --git a/pkg/services/pluginsintegration/clientmiddleware/tracing_header_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/tracing_header_middleware_test.go index b190dcc86fa..7b1df5a8065 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/tracing_header_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/tracing_header_middleware_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/grafana/grafana/pkg/services/user" "github.com/stretchr/testify/require" ) @@ -25,15 +25,15 @@ func TestTracingHeaderMiddleware(t *testing.T) { } t.Run("tracing headers are not set for query data", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{ + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{ IsAnonymous: true, Login: "anonymous"}, ), - clienttest.WithMiddlewares(NewTracingHeaderMiddleware()), + handlertest.WithMiddlewares(NewTracingHeaderMiddleware()), ) - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -43,15 +43,15 @@ func TestTracingHeaderMiddleware(t *testing.T) { }) t.Run("tracing headers are not set for health check", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{ + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{ IsAnonymous: true, Login: "anonymous"}, ), - clienttest.WithMiddlewares(NewTracingHeaderMiddleware()), + handlertest.WithMiddlewares(NewTracingHeaderMiddleware()), ) - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -69,15 +69,15 @@ func TestTracingHeaderMiddleware(t *testing.T) { } t.Run("tracing headers are not set for query data", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{ + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{ IsAnonymous: true, Login: "anonymous"}, ), - clienttest.WithMiddlewares(NewTracingHeaderMiddleware()), + handlertest.WithMiddlewares(NewTracingHeaderMiddleware()), ) - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -87,15 +87,15 @@ func TestTracingHeaderMiddleware(t *testing.T) { }) t.Run("tracing headers are not set for health check", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{ + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{ IsAnonymous: true, Login: "anonymous"}, ), - clienttest.WithMiddlewares(NewTracingHeaderMiddleware()), + handlertest.WithMiddlewares(NewTracingHeaderMiddleware()), ) - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -120,15 +120,15 @@ func TestTracingHeaderMiddleware(t *testing.T) { } t.Run("tracing headers are set for query data", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{ + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{ IsAnonymous: true, Login: "anonymous"}, ), - clienttest.WithMiddlewares(NewTracingHeaderMiddleware()), + handlertest.WithMiddlewares(NewTracingHeaderMiddleware()), ) - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -144,15 +144,15 @@ func TestTracingHeaderMiddleware(t *testing.T) { }) t.Run("tracing headers are set for health check", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{ + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{ IsAnonymous: true, Login: "anonymous"}, ), - clienttest.WithMiddlewares(NewTracingHeaderMiddleware()), + handlertest.WithMiddlewares(NewTracingHeaderMiddleware()), ) - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) diff --git a/pkg/services/pluginsintegration/clientmiddleware/tracing_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/tracing_middleware.go index d34d1635053..a4250de0047 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/tracing_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/tracing_middleware.go @@ -11,24 +11,23 @@ import ( "go.opentelemetry.io/otel/trace" "github.com/grafana/grafana/pkg/infra/tracing" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/query" ) // NewTracingMiddleware returns a new middleware that creates a new span on every method call. -func NewTracingMiddleware(tracer tracing.Tracer) plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func NewTracingMiddleware(tracer tracing.Tracer) backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &TracingMiddleware{ - tracer: tracer, - next: next, + tracer: tracer, + BaseHandler: backend.NewBaseHandler(next), } }) } type TracingMiddleware struct { + backend.BaseHandler tracer tracing.Tracer - next plugins.Client } // setSpanAttributeFromHTTPHeader takes a ReqContext and a span, and adds the specified HTTP header as a span attribute @@ -84,7 +83,7 @@ func (m *TracingMiddleware) QueryData(ctx context.Context, req *backend.QueryDat var err error ctx, end := m.traceWrap(ctx, req.PluginContext) defer func() { end(err) }() - resp, err := m.next.QueryData(ctx, req) + resp, err := m.BaseHandler.QueryData(ctx, req) return resp, err } @@ -92,7 +91,7 @@ func (m *TracingMiddleware) CallResource(ctx context.Context, req *backend.CallR var err error ctx, end := m.traceWrap(ctx, req.PluginContext) defer func() { end(err) }() - err = m.next.CallResource(ctx, req, sender) + err = m.BaseHandler.CallResource(ctx, req, sender) return err } @@ -100,7 +99,7 @@ func (m *TracingMiddleware) CheckHealth(ctx context.Context, req *backend.CheckH var err error ctx, end := m.traceWrap(ctx, req.PluginContext) defer func() { end(err) }() - resp, err := m.next.CheckHealth(ctx, req) + resp, err := m.BaseHandler.CheckHealth(ctx, req) return resp, err } @@ -108,7 +107,7 @@ func (m *TracingMiddleware) CollectMetrics(ctx context.Context, req *backend.Col var err error ctx, end := m.traceWrap(ctx, req.PluginContext) defer func() { end(err) }() - resp, err := m.next.CollectMetrics(ctx, req) + resp, err := m.BaseHandler.CollectMetrics(ctx, req) return resp, err } @@ -116,7 +115,7 @@ func (m *TracingMiddleware) SubscribeStream(ctx context.Context, req *backend.Su var err error ctx, end := m.traceWrap(ctx, req.PluginContext) defer func() { end(err) }() - resp, err := m.next.SubscribeStream(ctx, req) + resp, err := m.BaseHandler.SubscribeStream(ctx, req) return resp, err } @@ -124,7 +123,7 @@ func (m *TracingMiddleware) PublishStream(ctx context.Context, req *backend.Publ var err error ctx, end := m.traceWrap(ctx, req.PluginContext) defer func() { end(err) }() - resp, err := m.next.PublishStream(ctx, req) + resp, err := m.BaseHandler.PublishStream(ctx, req) return resp, err } @@ -132,7 +131,7 @@ func (m *TracingMiddleware) RunStream(ctx context.Context, req *backend.RunStrea var err error ctx, end := m.traceWrap(ctx, req.PluginContext) defer func() { end(err) }() - err = m.next.RunStream(ctx, req, sender) + err = m.BaseHandler.RunStream(ctx, req, sender) return err } @@ -141,7 +140,7 @@ func (m *TracingMiddleware) ValidateAdmission(ctx context.Context, req *backend. var err error ctx, end := m.traceWrap(ctx, req.PluginContext) defer func() { end(err) }() - resp, err := m.next.ValidateAdmission(ctx, req) + resp, err := m.BaseHandler.ValidateAdmission(ctx, req) return resp, err } @@ -150,7 +149,7 @@ func (m *TracingMiddleware) MutateAdmission(ctx context.Context, req *backend.Ad var err error ctx, end := m.traceWrap(ctx, req.PluginContext) defer func() { end(err) }() - resp, err := m.next.MutateAdmission(ctx, req) + resp, err := m.BaseHandler.MutateAdmission(ctx, req) return resp, err } @@ -159,6 +158,6 @@ func (m *TracingMiddleware) ConvertObjects(ctx context.Context, req *backend.Con var err error ctx, end := m.traceWrap(ctx, req.PluginContext) defer func() { end(err) }() - resp, err := m.next.ConvertObjects(ctx, req) + resp, err := m.BaseHandler.ConvertObjects(ctx, req) return resp, err } diff --git a/pkg/services/pluginsintegration/clientmiddleware/tracing_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/tracing_middleware_test.go index 249a66bd94f..78441fa5b8d 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/tracing_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/tracing_middleware_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/attribute" @@ -16,8 +17,6 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.17.0" "github.com/grafana/grafana/pkg/infra/tracing" - "github.com/grafana/grafana/pkg/plugins" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" "github.com/grafana/grafana/pkg/services/contexthandler/ctxkey" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" "github.com/grafana/grafana/pkg/web" @@ -30,13 +29,13 @@ func TestTracingMiddleware(t *testing.T) { for _, tc := range []struct { name string - run func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error + run func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error expSpanName string }{ { name: "QueryData", - run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error { - _, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{ + run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error { + _, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{ PluginContext: pluginCtx, }) return err @@ -45,8 +44,8 @@ func TestTracingMiddleware(t *testing.T) { }, { name: "CallResource", - run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error { - return cdt.Decorator.CallResource(context.Background(), &backend.CallResourceRequest{ + run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error { + return cdt.MiddlewareHandler.CallResource(context.Background(), &backend.CallResourceRequest{ PluginContext: pluginCtx, }, nopCallResourceSender) }, @@ -54,8 +53,8 @@ func TestTracingMiddleware(t *testing.T) { }, { name: "CheckHealth", - run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error { - _, err := cdt.Decorator.CheckHealth(context.Background(), &backend.CheckHealthRequest{ + run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error { + _, err := cdt.MiddlewareHandler.CheckHealth(context.Background(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, }) return err @@ -64,8 +63,8 @@ func TestTracingMiddleware(t *testing.T) { }, { name: "CollectMetrics", - run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error { - _, err := cdt.Decorator.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{ + run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error { + _, err := cdt.MiddlewareHandler.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{ PluginContext: pluginCtx, }) return err @@ -74,8 +73,8 @@ func TestTracingMiddleware(t *testing.T) { }, { name: "SubscribeStream", - run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error { - _, err := cdt.Decorator.SubscribeStream(context.Background(), &backend.SubscribeStreamRequest{ + run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error { + _, err := cdt.MiddlewareHandler.SubscribeStream(context.Background(), &backend.SubscribeStreamRequest{ PluginContext: pluginCtx, }) return err @@ -84,8 +83,8 @@ func TestTracingMiddleware(t *testing.T) { }, { name: "PublishStream", - run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error { - _, err := cdt.Decorator.PublishStream(context.Background(), &backend.PublishStreamRequest{ + run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error { + _, err := cdt.MiddlewareHandler.PublishStream(context.Background(), &backend.PublishStreamRequest{ PluginContext: pluginCtx, }) return err @@ -94,8 +93,8 @@ func TestTracingMiddleware(t *testing.T) { }, { name: "RunStream", - run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error { - return cdt.Decorator.RunStream(context.Background(), &backend.RunStreamRequest{ + run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error { + return cdt.MiddlewareHandler.RunStream(context.Background(), &backend.RunStreamRequest{ PluginContext: pluginCtx, }, &backend.StreamSender{}) }, @@ -107,9 +106,9 @@ func TestTracingMiddleware(t *testing.T) { spanRecorder := tracetest.NewSpanRecorder() tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder)) - cdt := clienttest.NewClientDecoratorTest( + cdt := handlertest.NewHandlerMiddlewareTest( t, - clienttest.WithMiddlewares(NewTracingMiddleware(tracer)), + handlertest.WithMiddlewares(NewTracingMiddleware(tracer)), ) err := tc.run(pluginCtx, cdt) @@ -126,9 +125,9 @@ func TestTracingMiddleware(t *testing.T) { spanRecorder := tracetest.NewSpanRecorder() tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder)) - cdt := clienttest.NewClientDecoratorTest( + cdt := handlertest.NewHandlerMiddlewareTest( t, - clienttest.WithMiddlewares( + handlertest.WithMiddlewares( NewTracingMiddleware(tracer), newAlwaysErrorMiddleware(errors.New("ops")), ), @@ -150,9 +149,9 @@ func TestTracingMiddleware(t *testing.T) { spanRecorder := tracetest.NewSpanRecorder() tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder)) - cdt := clienttest.NewClientDecoratorTest( + cdt := handlertest.NewHandlerMiddlewareTest( t, - clienttest.WithMiddlewares( + handlertest.WithMiddlewares( NewTracingMiddleware(tracer), newAlwaysPanicMiddleware("panic!"), ), @@ -314,12 +313,12 @@ func TestTracingMiddlewareAttributes(t *testing.T) { spanRecorder := tracetest.NewSpanRecorder() tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder)) - cdt := clienttest.NewClientDecoratorTest( + cdt := handlertest.NewHandlerMiddlewareTest( t, - clienttest.WithMiddlewares(NewTracingMiddleware(tracer)), + handlertest.WithMiddlewares(NewTracingMiddleware(tracer)), ) - _, err := cdt.Decorator.QueryData(ctx, req) + _, err := cdt.MiddlewareHandler.QueryData(ctx, req) require.NoError(t, err) spans := spanRecorder.Ended() require.Len(t, spans, 1, "must have 1 span") @@ -403,8 +402,8 @@ func (m *alwaysErrorFuncMiddleware) ConvertObjects(ctx context.Context, req *bac } // newAlwaysErrorMiddleware returns a new middleware that always returns the specified error. -func newAlwaysErrorMiddleware(err error) plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func newAlwaysErrorMiddleware(err error) backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &alwaysErrorFuncMiddleware{func() error { return err }} @@ -412,8 +411,8 @@ func newAlwaysErrorMiddleware(err error) plugins.ClientMiddleware { } // newAlwaysPanicMiddleware returns a new middleware that always panics with the specified message, -func newAlwaysPanicMiddleware(message string) plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +func newAlwaysPanicMiddleware(message string) backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &alwaysErrorFuncMiddleware{func() error { panic(message) }} diff --git a/pkg/services/pluginsintegration/clientmiddleware/user_header_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/user_header_middleware.go index 214b1305979..c3dbde59567 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/user_header_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/user_header_middleware.go @@ -6,25 +6,22 @@ import ( "github.com/grafana/authlib/claims" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/util/proxyutil" ) -// NewUserHeaderMiddleware creates a new plugins.ClientMiddleware that will -// populate the X-Grafana-User header on outgoing plugins.Client requests. -func NewUserHeaderMiddleware() plugins.ClientMiddleware { - return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client { +// NewUserHeaderMiddleware creates a new backend.HandlerMiddleware that will +// populate the X-Grafana-User header on outgoing backend.Handler requests. +func NewUserHeaderMiddleware() backend.HandlerMiddleware { + return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler { return &UserHeaderMiddleware{ - baseMiddleware: baseMiddleware{ - next: next, - }, + BaseHandler: backend.NewBaseHandler(next), } }) } type UserHeaderMiddleware struct { - baseMiddleware + backend.BaseHandler } func (m *UserHeaderMiddleware) applyUserHeader(ctx context.Context, h backend.ForwardHTTPHeaders) { @@ -42,30 +39,30 @@ func (m *UserHeaderMiddleware) applyUserHeader(ctx context.Context, h backend.Fo func (m *UserHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { if req == nil { - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } m.applyUserHeader(ctx, req) - return m.next.QueryData(ctx, req) + return m.BaseHandler.QueryData(ctx, req) } func (m *UserHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { if req == nil { - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } m.applyUserHeader(ctx, req) - return m.next.CallResource(ctx, req, sender) + return m.BaseHandler.CallResource(ctx, req, sender) } func (m *UserHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { if req == nil { - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } m.applyUserHeader(ctx, req) - return m.next.CheckHealth(ctx, req) + return m.BaseHandler.CheckHealth(ctx, req) } diff --git a/pkg/services/pluginsintegration/clientmiddleware/user_header_middleware_test.go b/pkg/services/pluginsintegration/clientmiddleware/user_header_middleware_test.go index 9fedd33a0e2..327705bd1f6 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/user_header_middleware_test.go +++ b/pkg/services/pluginsintegration/clientmiddleware/user_header_middleware_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/plugins/manager/client/clienttest" + "github.com/grafana/grafana-plugin-sdk-go/backend/handlertest" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/util/proxyutil" "github.com/stretchr/testify/require" @@ -17,12 +17,12 @@ func TestUserHeaderMiddleware(t *testing.T) { require.NoError(t, err) t.Run("And requests are for a datasource", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{ + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{ IsAnonymous: true, Login: "anonymous"}, ), - clienttest.WithMiddlewares(NewUserHeaderMiddleware()), + handlertest.WithMiddlewares(NewUserHeaderMiddleware()), ) pluginCtx := backend.PluginContext{ @@ -30,7 +30,7 @@ func TestUserHeaderMiddleware(t *testing.T) { } t.Run("Should not forward user header when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -40,7 +40,7 @@ func TestUserHeaderMiddleware(t *testing.T) { }) t.Run("Should not forward user header when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{}, }, nopCallResourceSender) @@ -50,7 +50,7 @@ func TestUserHeaderMiddleware(t *testing.T) { }) t.Run("Should not forward user header when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -61,12 +61,12 @@ func TestUserHeaderMiddleware(t *testing.T) { }) t.Run("And requests are for an app", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{ + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{ IsAnonymous: true, Login: "anonymous"}, ), - clienttest.WithMiddlewares(NewUserHeaderMiddleware()), + handlertest.WithMiddlewares(NewUserHeaderMiddleware()), ) pluginCtx := backend.PluginContext{ @@ -74,7 +74,7 @@ func TestUserHeaderMiddleware(t *testing.T) { } t.Run("Should not forward user header when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -84,7 +84,7 @@ func TestUserHeaderMiddleware(t *testing.T) { }) t.Run("Should not forward user header when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{}, }, nopCallResourceSender) @@ -94,7 +94,7 @@ func TestUserHeaderMiddleware(t *testing.T) { }) t.Run("Should not forward user header when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -110,11 +110,11 @@ func TestUserHeaderMiddleware(t *testing.T) { require.NoError(t, err) t.Run("And requests are for a datasource", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{ + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{ Login: "admin", }), - clienttest.WithMiddlewares(NewUserHeaderMiddleware()), + handlertest.WithMiddlewares(NewUserHeaderMiddleware()), ) pluginCtx := backend.PluginContext{ @@ -122,7 +122,7 @@ func TestUserHeaderMiddleware(t *testing.T) { } t.Run("Should forward user header when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -133,7 +133,7 @@ func TestUserHeaderMiddleware(t *testing.T) { }) t.Run("Should forward user header when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{}, }, nopCallResourceSender) @@ -144,7 +144,7 @@ func TestUserHeaderMiddleware(t *testing.T) { }) t.Run("Should forward user header when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -156,11 +156,11 @@ func TestUserHeaderMiddleware(t *testing.T) { }) t.Run("And requests are for an app", func(t *testing.T) { - cdt := clienttest.NewClientDecoratorTest(t, - clienttest.WithReqContext(req, &user.SignedInUser{ + cdt := handlertest.NewHandlerMiddlewareTest(t, + WithReqContext(req, &user.SignedInUser{ Login: "admin", }), - clienttest.WithMiddlewares(NewUserHeaderMiddleware()), + handlertest.WithMiddlewares(NewUserHeaderMiddleware()), ) pluginCtx := backend.PluginContext{ @@ -168,7 +168,7 @@ func TestUserHeaderMiddleware(t *testing.T) { } t.Run("Should forward user header when calling QueryData", func(t *testing.T) { - _, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{ + _, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) @@ -179,7 +179,7 @@ func TestUserHeaderMiddleware(t *testing.T) { }) t.Run("Should forward user header when calling CallResource", func(t *testing.T) { - err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{ + err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{ PluginContext: pluginCtx, Headers: map[string][]string{}, }, nopCallResourceSender) @@ -190,7 +190,7 @@ func TestUserHeaderMiddleware(t *testing.T) { }) t.Run("Should forward user header when calling CheckHealth", func(t *testing.T) { - _, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{ + _, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{ PluginContext: pluginCtx, Headers: map[string]string{}, }) diff --git a/pkg/services/pluginsintegration/pluginsintegration.go b/pkg/services/pluginsintegration/pluginsintegration.go index a699982efd8..36c20fa8cbc 100644 --- a/pkg/services/pluginsintegration/pluginsintegration.go +++ b/pkg/services/pluginsintegration/pluginsintegration.go @@ -3,6 +3,7 @@ package pluginsintegration import ( "github.com/google/wire" + "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/prometheus/client_golang/prometheus" "github.com/grafana/grafana/pkg/infra/tracing" @@ -139,13 +140,13 @@ var WireExtensionSet = wire.NewSet( wire.Bind(new(plugins.PluginLoaderAuthorizer), new(*signature.UnsignedPluginAuthorizer)), finder.ProvideLocalFinder, wire.Bind(new(finder.Finder), new(*finder.Local)), - ProvideClientDecorator, - wire.Bind(new(plugins.Client), new(*client.Decorator)), + ProvideClientWithMiddlewares, + wire.Bind(new(plugins.Client), new(*backend.MiddlewareHandler)), managedplugins.NewNoop, wire.Bind(new(managedplugins.Manager), new(*managedplugins.Noop)), ) -func ProvideClientDecorator( +func ProvideClientWithMiddlewares( cfg *setting.Cfg, pluginRegistry registry.Service, oAuthTokenService oauthtoken.OAuthTokenService, @@ -153,23 +154,23 @@ func ProvideClientDecorator( cachingService caching.CachingService, features featuremgmt.FeatureToggles, promRegisterer prometheus.Registerer, -) (*client.Decorator, error) { - return NewClientDecorator(cfg, pluginRegistry, oAuthTokenService, tracer, cachingService, features, promRegisterer, pluginRegistry) +) (*backend.MiddlewareHandler, error) { + return NewMiddlewareHandler(cfg, pluginRegistry, oAuthTokenService, tracer, cachingService, features, promRegisterer, pluginRegistry) } -func NewClientDecorator( +func NewMiddlewareHandler( cfg *setting.Cfg, pluginRegistry registry.Service, oAuthTokenService oauthtoken.OAuthTokenService, tracer tracing.Tracer, cachingService caching.CachingService, features featuremgmt.FeatureToggles, promRegisterer prometheus.Registerer, registry registry.Service, -) (*client.Decorator, error) { +) (*backend.MiddlewareHandler, error) { c := client.ProvideService(pluginRegistry) middlewares := CreateMiddlewares(cfg, oAuthTokenService, tracer, cachingService, features, promRegisterer, registry) - return client.NewDecorator(c, middlewares...) + return backend.HandlerFromMiddlewares(c, middlewares...) } -func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthTokenService, tracer tracing.Tracer, cachingService caching.CachingService, features featuremgmt.FeatureToggles, promRegisterer prometheus.Registerer, registry registry.Service) []plugins.ClientMiddleware { - middlewares := []plugins.ClientMiddleware{ +func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthTokenService, tracer tracing.Tracer, cachingService caching.CachingService, features featuremgmt.FeatureToggles, promRegisterer prometheus.Registerer, registry registry.Service) []backend.HandlerMiddleware { + middlewares := []backend.HandlerMiddleware{ clientmiddleware.NewPluginRequestMetaMiddleware(), clientmiddleware.NewTracingMiddleware(tracer), clientmiddleware.NewMetricsMiddleware(promRegisterer, registry), @@ -187,7 +188,6 @@ func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthToken clientmiddleware.NewClearAuthHeadersMiddleware(), clientmiddleware.NewOAuthTokenMiddleware(oAuthTokenService), clientmiddleware.NewCookiesMiddleware(skipCookiesNames), - clientmiddleware.NewResourceResponseMiddleware(), clientmiddleware.NewCachingMiddlewareWithFeatureManager(cachingService, features), clientmiddleware.NewForwardIDMiddleware(), )