Chore: Remove bus from plugin proxy api (#44899)

* remove bus from plugin proxy api

* fixing the tests
pull/44869/head
Serge Zaitsev 3 years ago committed by GitHub
parent 7a23700e1a
commit 9d654bb6b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      pkg/api/app_routes.go
  2. 6
      pkg/api/pluginproxy/pluginproxy.go
  3. 67
      pkg/api/pluginproxy/pluginproxy_test.go
  4. 3
      pkg/services/sqlstore/mockstore/mockstore.go

@ -63,7 +63,7 @@ func AppPluginRoute(route *plugins.Route, appID string, hs *HTTPServer) web.Hand
return func(c *models.ReqContext) { return func(c *models.ReqContext) {
path := web.Params(c.Req)["*"] path := web.Params(c.Req)["*"]
proxy := pluginproxy.NewApiPluginProxy(c, path, route, appID, hs.Cfg, hs.SecretsService) proxy := pluginproxy.NewApiPluginProxy(c, path, route, appID, hs.Cfg, hs.SQLStore, hs.SecretsService)
proxy.Transport = pluginProxyTransport proxy.Transport = pluginProxyTransport
proxy.ServeHTTP(c.Resp, c.Req) proxy.ServeHTTP(c.Resp, c.Req)
} }

@ -6,10 +6,10 @@ import (
"net/http/httputil" "net/http/httputil"
"net/url" "net/url"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/secrets" "github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/util/proxyutil" "github.com/grafana/grafana/pkg/util/proxyutil"
@ -22,10 +22,10 @@ type templateData struct {
// NewApiPluginProxy create a plugin proxy // NewApiPluginProxy create a plugin proxy
func NewApiPluginProxy(ctx *models.ReqContext, proxyPath string, route *plugins.Route, func NewApiPluginProxy(ctx *models.ReqContext, proxyPath string, route *plugins.Route,
appID string, cfg *setting.Cfg, secretsService secrets.Service) *httputil.ReverseProxy { appID string, cfg *setting.Cfg, store sqlstore.Store, secretsService secrets.Service) *httputil.ReverseProxy {
director := func(req *http.Request) { director := func(req *http.Request) {
query := models.GetPluginSettingByIdQuery{OrgId: ctx.OrgId, PluginId: appID} query := models.GetPluginSettingByIdQuery{OrgId: ctx.OrgId, PluginId: appID}
if err := bus.Dispatch(ctx.Req.Context(), &query); err != nil { if err := store.GetPluginSettingById(ctx.Req.Context(), &query); err != nil {
ctx.JsonApiErr(500, "Failed to fetch plugin settings", err) ctx.JsonApiErr(500, "Failed to fetch plugin settings", err)
return return
} }

@ -6,12 +6,13 @@ import (
"net/http" "net/http"
"testing" "testing"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/secrets" "github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/services/secrets/fakes" "github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -28,20 +29,13 @@ func TestPluginProxy(t *testing.T) {
{Name: "x-header", Content: "my secret {{.SecureJsonData.key}}"}, {Name: "x-header", Content: "my secret {{.SecureJsonData.key}}"},
}, },
} }
store := mockstore.NewSQLStoreMock()
bus.AddHandler("test", func(ctx context.Context, query *models.GetPluginSettingByIdQuery) error { key, _ := secretsService.Encrypt(context.Background(), []byte("123"), secrets.WithoutScope())
key, err := secretsService.Encrypt(ctx, []byte("123"), secrets.WithoutScope()) store.ExpectedPluginSetting = &models.PluginSetting{
if err != nil {
return err
}
query.Result = &models.PluginSetting{
SecureJsonData: map[string][]byte{ SecureJsonData: map[string][]byte{
"key": key, "key": key,
}, },
} }
return nil
})
httpReq, err := http.NewRequest(http.MethodGet, "", nil) httpReq, err := http.NewRequest(http.MethodGet, "", nil)
require.NoError(t, err) require.NoError(t, err)
@ -59,6 +53,7 @@ func TestPluginProxy(t *testing.T) {
}, },
&setting.Cfg{SendUserHeader: true}, &setting.Cfg{SendUserHeader: true},
route, route,
store,
) )
assert.Equal(t, "my secret 123", req.Header.Get("x-header")) assert.Equal(t, "my secret 123", req.Header.Get("x-header"))
@ -67,6 +62,8 @@ func TestPluginProxy(t *testing.T) {
t.Run("When SendUserHeader config is enabled", func(t *testing.T) { t.Run("When SendUserHeader config is enabled", func(t *testing.T) {
httpReq, err := http.NewRequest(http.MethodGet, "", nil) httpReq, err := http.NewRequest(http.MethodGet, "", nil)
require.NoError(t, err) require.NoError(t, err)
store := mockstore.NewSQLStoreMock()
store.ExpectedPluginSetting = &models.PluginSetting{}
req := getPluginProxiedRequest( req := getPluginProxiedRequest(
t, t,
@ -81,6 +78,7 @@ func TestPluginProxy(t *testing.T) {
}, },
&setting.Cfg{SendUserHeader: true}, &setting.Cfg{SendUserHeader: true},
nil, nil,
store,
) )
// Get will return empty string even if header is not set // Get will return empty string even if header is not set
@ -90,6 +88,8 @@ func TestPluginProxy(t *testing.T) {
t.Run("When SendUserHeader config is disabled", func(t *testing.T) { t.Run("When SendUserHeader config is disabled", func(t *testing.T) {
httpReq, err := http.NewRequest(http.MethodGet, "", nil) httpReq, err := http.NewRequest(http.MethodGet, "", nil)
require.NoError(t, err) require.NoError(t, err)
store := mockstore.NewSQLStoreMock()
store.ExpectedPluginSetting = &models.PluginSetting{}
req := getPluginProxiedRequest( req := getPluginProxiedRequest(
t, t,
@ -104,6 +104,7 @@ func TestPluginProxy(t *testing.T) {
}, },
&setting.Cfg{SendUserHeader: false}, &setting.Cfg{SendUserHeader: false},
nil, nil,
store,
) )
// Get will return empty string even if header is not set // Get will return empty string even if header is not set
assert.Equal(t, "", req.Header.Get("X-Grafana-User")) assert.Equal(t, "", req.Header.Get("X-Grafana-User"))
@ -112,6 +113,8 @@ func TestPluginProxy(t *testing.T) {
t.Run("When SendUserHeader config is enabled but user is anonymous", func(t *testing.T) { t.Run("When SendUserHeader config is enabled but user is anonymous", func(t *testing.T) {
httpReq, err := http.NewRequest(http.MethodGet, "", nil) httpReq, err := http.NewRequest(http.MethodGet, "", nil)
require.NoError(t, err) require.NoError(t, err)
store := mockstore.NewSQLStoreMock()
store.ExpectedPluginSetting = &models.PluginSetting{}
req := getPluginProxiedRequest( req := getPluginProxiedRequest(
t, t,
@ -124,6 +127,7 @@ func TestPluginProxy(t *testing.T) {
}, },
&setting.Cfg{SendUserHeader: true}, &setting.Cfg{SendUserHeader: true},
nil, nil,
store,
) )
// Get will return empty string even if header is not set // Get will return empty string even if header is not set
@ -135,15 +139,12 @@ func TestPluginProxy(t *testing.T) {
URL: "{{.JsonData.dynamicUrl}}", URL: "{{.JsonData.dynamicUrl}}",
Method: "GET", Method: "GET",
} }
store := mockstore.NewSQLStoreMock()
bus.AddHandler("test", func(_ context.Context, query *models.GetPluginSettingByIdQuery) error { store.ExpectedPluginSetting = &models.PluginSetting{
query.Result = &models.PluginSetting{
JsonData: map[string]interface{}{ JsonData: map[string]interface{}{
"dynamicUrl": "https://dynamic.grafana.com", "dynamicUrl": "https://dynamic.grafana.com",
}, },
} }
return nil
})
httpReq, err := http.NewRequest(http.MethodGet, "", nil) httpReq, err := http.NewRequest(http.MethodGet, "", nil)
require.NoError(t, err) require.NoError(t, err)
@ -161,6 +162,7 @@ func TestPluginProxy(t *testing.T) {
}, },
&setting.Cfg{SendUserHeader: true}, &setting.Cfg{SendUserHeader: true},
route, route,
store,
) )
assert.Equal(t, "https://dynamic.grafana.com", req.URL.String()) assert.Equal(t, "https://dynamic.grafana.com", req.URL.String())
assert.Equal(t, "{{.JsonData.dynamicUrl}}", route.URL) assert.Equal(t, "{{.JsonData.dynamicUrl}}", route.URL)
@ -171,11 +173,8 @@ func TestPluginProxy(t *testing.T) {
URL: "{{if .JsonData.apiHost}}{{.JsonData.apiHost}}{{else}}https://example.com{{end}}", URL: "{{if .JsonData.apiHost}}{{.JsonData.apiHost}}{{else}}https://example.com{{end}}",
Method: "GET", Method: "GET",
} }
store := mockstore.NewSQLStoreMock()
bus.AddHandler("test", func(_ context.Context, query *models.GetPluginSettingByIdQuery) error { store.ExpectedPluginSetting = &models.PluginSetting{}
query.Result = &models.PluginSetting{}
return nil
})
httpReq, err := http.NewRequest(http.MethodGet, "", nil) httpReq, err := http.NewRequest(http.MethodGet, "", nil)
require.NoError(t, err) require.NoError(t, err)
@ -193,6 +192,7 @@ func TestPluginProxy(t *testing.T) {
}, },
&setting.Cfg{SendUserHeader: true}, &setting.Cfg{SendUserHeader: true},
route, route,
store,
) )
assert.Equal(t, "https://example.com", req.URL.String()) assert.Equal(t, "https://example.com", req.URL.String())
}) })
@ -204,25 +204,17 @@ func TestPluginProxy(t *testing.T) {
Body: []byte(`{ "url": "{{.JsonData.dynamicUrl}}", "secret": "{{.SecureJsonData.key}}" }`), Body: []byte(`{ "url": "{{.JsonData.dynamicUrl}}", "secret": "{{.SecureJsonData.key}}" }`),
} }
bus.AddHandler("test", func(ctx context.Context, query *models.GetPluginSettingByIdQuery) error { store := mockstore.NewSQLStoreMock()
encryptedJsonData, err := secretsService.EncryptJsonData(
ctx, encryptedJsonData, _ := secretsService.EncryptJsonData(
context.Background(),
map[string]string{"key": "123"}, map[string]string{"key": "123"},
secrets.WithoutScope(), secrets.WithoutScope(),
) )
store.ExpectedPluginSetting = &models.PluginSetting{
if err != nil { JsonData: map[string]interface{}{"dynamicUrl": "https://dynamic.grafana.com"},
return err
}
query.Result = &models.PluginSetting{
JsonData: map[string]interface{}{
"dynamicUrl": "https://dynamic.grafana.com",
},
SecureJsonData: encryptedJsonData, SecureJsonData: encryptedJsonData,
} }
return nil
})
httpReq, err := http.NewRequest(http.MethodGet, "", nil) httpReq, err := http.NewRequest(http.MethodGet, "", nil)
require.NoError(t, err) require.NoError(t, err)
@ -240,6 +232,7 @@ func TestPluginProxy(t *testing.T) {
}, },
&setting.Cfg{SendUserHeader: true}, &setting.Cfg{SendUserHeader: true},
route, route,
store,
) )
content, err := ioutil.ReadAll(req.Body) content, err := ioutil.ReadAll(req.Body)
require.NoError(t, err) require.NoError(t, err)
@ -248,7 +241,7 @@ func TestPluginProxy(t *testing.T) {
} }
// getPluginProxiedRequest is a helper for easier setup of tests based on global config and ReqContext. // getPluginProxiedRequest is a helper for easier setup of tests based on global config and ReqContext.
func getPluginProxiedRequest(t *testing.T, secretsService secrets.Service, ctx *models.ReqContext, cfg *setting.Cfg, route *plugins.Route) *http.Request { func getPluginProxiedRequest(t *testing.T, secretsService secrets.Service, ctx *models.ReqContext, cfg *setting.Cfg, route *plugins.Route, store sqlstore.Store) *http.Request {
// insert dummy route if none is specified // insert dummy route if none is specified
if route == nil { if route == nil {
route = &plugins.Route{ route = &plugins.Route{
@ -257,7 +250,7 @@ func getPluginProxiedRequest(t *testing.T, secretsService secrets.Service, ctx *
ReqRole: models.ROLE_EDITOR, ReqRole: models.ROLE_EDITOR,
} }
} }
proxy := NewApiPluginProxy(ctx, "", route, "", cfg, secretsService) proxy := NewApiPluginProxy(ctx, "", route, "", cfg, store, secretsService)
req, err := http.NewRequest(http.MethodGet, "/api/plugin-proxy/grafana-simple-app/api/v4/alerts", nil) req, err := http.NewRequest(http.MethodGet, "/api/plugin-proxy/grafana-simple-app/api/v4/alerts", nil)
require.NoError(t, err) require.NoError(t, err)

@ -14,6 +14,8 @@ type SQLStoreMock struct {
ExpectedUser *models.User ExpectedUser *models.User
ExpectedDatasource *models.DataSource ExpectedDatasource *models.DataSource
ExpectedAlert *models.Alert ExpectedAlert *models.Alert
ExpectedPluginSetting *models.PluginSetting
ExpectedError error ExpectedError error
} }
@ -239,6 +241,7 @@ func (m *SQLStoreMock) GetPluginSettings(ctx context.Context, orgID int64) ([]*m
} }
func (m *SQLStoreMock) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error { func (m *SQLStoreMock) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error {
query.Result = m.ExpectedPluginSetting
return m.ExpectedError return m.ExpectedError
} }

Loading…
Cancel
Save