Plugins: Unexport PluginDir field from PluginDTO (#59190)
* unexport pluginDir from dto * more err checks * tidy * fix tests * fix dboard file tests * fix import * fix tests * apply PR feedback * combine interfaces * fix logs and clean up test * filepath clean * use fs.File * rm explicit type
This commit is contained in:
+65
-101
@@ -12,7 +12,6 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
@@ -135,13 +134,13 @@ func Test_PluginsInstallAndUninstall_AccessControl(t *testing.T) {
|
||||
t.Run(testName("Install", tc), func(t *testing.T) {
|
||||
input := strings.NewReader("{ \"version\": \"1.0.2\" }")
|
||||
response := callAPI(sc.server, http.MethodPost, "/api/plugins/test/install", input, t)
|
||||
assert.Equal(t, tc.expectedCode, response.Code)
|
||||
require.Equal(t, tc.expectedCode, response.Code)
|
||||
})
|
||||
|
||||
t.Run(testName("Uninstall", tc), func(t *testing.T) {
|
||||
input := strings.NewReader("{ }")
|
||||
response := callAPI(sc.server, http.MethodPost, "/api/plugins/test/uninstall", input, t)
|
||||
assert.Equal(t, tc.expectedCode, response.Code)
|
||||
require.Equal(t, tc.expectedCode, response.Code)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -155,56 +154,45 @@ func Test_GetPluginAssets(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
err := os.RemoveAll(tmpFile.Name())
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
err = os.RemoveAll(tmpFileInParentDir.Name())
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
expectedBody := "Plugin test"
|
||||
_, err = tmpFile.WriteString(expectedBody)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
requestedFile := filepath.Clean(tmpFile.Name())
|
||||
|
||||
t.Run("Given a request for an existing plugin file that is listed as a signature covered file", func(t *testing.T) {
|
||||
p := plugins.PluginDTO{
|
||||
t.Run("Given a request for an existing plugin file", func(t *testing.T) {
|
||||
p := &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: pluginID,
|
||||
},
|
||||
PluginDir: pluginDir,
|
||||
SignedFiles: map[string]struct{}{
|
||||
requestedFile: {},
|
||||
},
|
||||
}
|
||||
service := &plugins.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{p},
|
||||
PluginList: []plugins.PluginDTO{p.ToDTO()},
|
||||
}
|
||||
l := &logtest.Fake{}
|
||||
|
||||
url := fmt.Sprintf("/public/plugins/%s/%s", pluginID, requestedFile)
|
||||
pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service, l,
|
||||
pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service,
|
||||
func(sc *scenarioContext) {
|
||||
callGetPluginAsset(sc)
|
||||
|
||||
require.Equal(t, 200, sc.resp.Code)
|
||||
assert.Equal(t, expectedBody, sc.resp.Body.String())
|
||||
assert.Zero(t, l.WarnLogs.Calls)
|
||||
require.Equal(t, expectedBody, sc.resp.Body.String())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Given a request for a relative path", func(t *testing.T) {
|
||||
p := plugins.PluginDTO{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: pluginID,
|
||||
},
|
||||
PluginDir: pluginDir,
|
||||
}
|
||||
p := createPluginDTO(plugins.JSONData{ID: pluginID}, plugins.External, pluginDir)
|
||||
service := &plugins.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{p},
|
||||
}
|
||||
l := &logtest.Fake{}
|
||||
|
||||
url := fmt.Sprintf("/public/plugins/%s/%s", pluginID, tmpFileInParentDir.Name())
|
||||
pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service, l,
|
||||
pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service,
|
||||
func(sc *scenarioContext) {
|
||||
callGetPluginAsset(sc)
|
||||
|
||||
@@ -212,44 +200,15 @@ func Test_GetPluginAssets(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Given a request for an existing plugin file that is not listed as a signature covered file", func(t *testing.T) {
|
||||
p := plugins.PluginDTO{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: pluginID,
|
||||
},
|
||||
PluginDir: pluginDir,
|
||||
}
|
||||
service := &plugins.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{p},
|
||||
}
|
||||
l := &logtest.Fake{}
|
||||
|
||||
url := fmt.Sprintf("/public/plugins/%s/%s", pluginID, requestedFile)
|
||||
pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service, l,
|
||||
func(sc *scenarioContext) {
|
||||
callGetPluginAsset(sc)
|
||||
|
||||
require.Equal(t, 200, sc.resp.Code)
|
||||
assert.Equal(t, expectedBody, sc.resp.Body.String())
|
||||
assert.Zero(t, l.WarnLogs.Calls)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Given a request for an non-existing plugin file", func(t *testing.T) {
|
||||
p := plugins.PluginDTO{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: pluginID,
|
||||
},
|
||||
PluginDir: pluginDir,
|
||||
}
|
||||
p := createPluginDTO(plugins.JSONData{ID: pluginID}, plugins.External, pluginDir)
|
||||
service := &plugins.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{p},
|
||||
}
|
||||
l := &logtest.Fake{}
|
||||
|
||||
requestedFile := "nonExistent"
|
||||
url := fmt.Sprintf("/public/plugins/%s/%s", pluginID, requestedFile)
|
||||
pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service, l,
|
||||
pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service,
|
||||
func(sc *scenarioContext) {
|
||||
callGetPluginAsset(sc)
|
||||
|
||||
@@ -257,8 +216,7 @@ func Test_GetPluginAssets(t *testing.T) {
|
||||
err := json.NewDecoder(sc.resp.Body).Decode(&respJson)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 404, sc.resp.Code)
|
||||
assert.Equal(t, "Plugin file not found", respJson["message"])
|
||||
assert.Zero(t, l.WarnLogs.Calls)
|
||||
require.Equal(t, "Plugin file not found", respJson["message"])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -270,16 +228,16 @@ func Test_GetPluginAssets(t *testing.T) {
|
||||
|
||||
requestedFile := "nonExistent"
|
||||
url := fmt.Sprintf("/public/plugins/%s/%s", pluginID, requestedFile)
|
||||
pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service, l,
|
||||
pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service,
|
||||
func(sc *scenarioContext) {
|
||||
callGetPluginAsset(sc)
|
||||
|
||||
var respJson map[string]interface{}
|
||||
err := json.NewDecoder(sc.resp.Body).Decode(&respJson)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 404, sc.resp.Code)
|
||||
assert.Equal(t, "Plugin not found", respJson["message"])
|
||||
assert.Zero(t, l.WarnLogs.Calls)
|
||||
require.Equal(t, 404, sc.resp.Code)
|
||||
require.Equal(t, "Plugin not found", respJson["message"])
|
||||
require.Zero(t, l.WarnLogs.Calls)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -295,13 +253,13 @@ func Test_GetPluginAssets(t *testing.T) {
|
||||
l := &logtest.Fake{}
|
||||
|
||||
url := fmt.Sprintf("/public/plugins/%s/%s", pluginID, requestedFile)
|
||||
pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service, l,
|
||||
pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service,
|
||||
func(sc *scenarioContext) {
|
||||
callGetPluginAsset(sc)
|
||||
|
||||
require.Equal(t, 200, sc.resp.Code)
|
||||
assert.Equal(t, expectedBody, sc.resp.Body.String())
|
||||
assert.Zero(t, l.WarnLogs.Calls)
|
||||
require.Equal(t, expectedBody, sc.resp.Body.String())
|
||||
require.Zero(t, l.WarnLogs.Calls)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -348,7 +306,7 @@ func TestMakePluginResourceRequestSetCookieNotPresent(t *testing.T) {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.Empty(t, resp.Header().Values("Set-Cookie"), "Set-Cookie header should not be present")
|
||||
require.Empty(t, resp.Header().Values("Set-Cookie"), "Set-Cookie header should not be present")
|
||||
}
|
||||
|
||||
func TestMakePluginResourceRequestContentTypeUnique(t *testing.T) {
|
||||
@@ -382,8 +340,8 @@ func TestMakePluginResourceRequestContentTypeUnique(t *testing.T) {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.Len(t, resp.Header().Values("Content-Type"), 1, "should have 1 Content-Type header")
|
||||
assert.Len(t, resp.Header().Values("x-another"), 1, "should have 1 X-Another header")
|
||||
require.Len(t, resp.Header().Values("Content-Type"), 1, "should have 1 Content-Type header")
|
||||
require.Len(t, resp.Header().Values("x-another"), 1, "should have 1 X-Another header")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -417,12 +375,11 @@ func callGetPluginAsset(sc *scenarioContext) {
|
||||
}
|
||||
|
||||
func pluginAssetScenario(t *testing.T, desc string, url string, urlPattern string, pluginStore plugins.Store,
|
||||
logger log.Logger, fn scenarioFunc) {
|
||||
fn scenarioFunc) {
|
||||
t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) {
|
||||
hs := HTTPServer{
|
||||
Cfg: setting.NewCfg(),
|
||||
pluginStore: pluginStore,
|
||||
log: logger,
|
||||
}
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
@@ -478,42 +435,40 @@ func (c *fakePluginClient) QueryData(ctx context.Context, req *backend.QueryData
|
||||
}
|
||||
|
||||
func Test_PluginsList_AccessControl(t *testing.T) {
|
||||
pluginStore := plugins.FakePluginStore{PluginList: []plugins.PluginDTO{
|
||||
{
|
||||
PluginDir: "/grafana/plugins/test-app/dist",
|
||||
Class: "external",
|
||||
DefaultNavURL: "/plugins/test-app/page/test",
|
||||
Pinned: false,
|
||||
Signature: "unsigned",
|
||||
Module: "plugins/test-app/module",
|
||||
BaseURL: "public/plugins/test-app",
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test-app",
|
||||
Type: "app",
|
||||
Name: "test-app",
|
||||
Info: plugins.Info{
|
||||
Version: "1.0.0",
|
||||
},
|
||||
p1 := &plugins.Plugin{
|
||||
PluginDir: "/grafana/plugins/test-app/dist",
|
||||
Class: plugins.External,
|
||||
DefaultNavURL: "/plugins/test-app/page/test",
|
||||
Signature: plugins.SignatureUnsigned,
|
||||
Module: "plugins/test-app/module",
|
||||
BaseURL: "public/plugins/test-app",
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test-app",
|
||||
Type: plugins.App,
|
||||
Name: "test-app",
|
||||
Info: plugins.Info{
|
||||
Version: "1.0.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
PluginDir: "/grafana/public/app/plugins/datasource/mysql",
|
||||
Class: "core",
|
||||
Pinned: false,
|
||||
Signature: "internal",
|
||||
Module: "app/plugins/datasource/mysql/module",
|
||||
BaseURL: "public/app/plugins/datasource/mysql",
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "mysql",
|
||||
Type: "datasource",
|
||||
Name: "MySQL",
|
||||
Info: plugins.Info{
|
||||
Author: plugins.InfoLink{Name: "Grafana Labs", URL: "https://grafana.com"},
|
||||
Description: "Data source for MySQL databases",
|
||||
},
|
||||
}
|
||||
p2 := &plugins.Plugin{
|
||||
PluginDir: "/grafana/public/app/plugins/datasource/mysql",
|
||||
Class: plugins.Core,
|
||||
Pinned: false,
|
||||
Signature: plugins.SignatureInternal,
|
||||
Module: "app/plugins/datasource/mysql/module",
|
||||
BaseURL: "public/app/plugins/datasource/mysql",
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "mysql",
|
||||
Type: plugins.DataSource,
|
||||
Name: "MySQL",
|
||||
Info: plugins.Info{
|
||||
Author: plugins.InfoLink{Name: "Grafana Labs", URL: "https://grafana.com"},
|
||||
Description: "Data source for MySQL databases",
|
||||
},
|
||||
},
|
||||
}}
|
||||
}
|
||||
pluginStore := plugins.FakePluginStore{PluginList: []plugins.PluginDTO{p1.ToDTO(), p2.ToDTO()}}
|
||||
|
||||
pluginSettings := pluginsettings.FakePluginSettings{Plugins: map[string]*pluginsettings.DTO{
|
||||
"test-app": {ID: 0, OrgID: 1, PluginID: "test-app", PluginVersion: "1.0.0", Enabled: true},
|
||||
@@ -574,3 +529,12 @@ func Test_PluginsList_AccessControl(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func createPluginDTO(jd plugins.JSONData, class plugins.Class, pluginDir string) plugins.PluginDTO {
|
||||
p := &plugins.Plugin{
|
||||
JSONData: jd,
|
||||
Class: class,
|
||||
PluginDir: pluginDir,
|
||||
}
|
||||
return p.ToDTO()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user