The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/services/updatemanager/plugins_test.go

302 lines
8.0 KiB

package updatemanager
import (
"context"
"io"
"net/http"
"net/url"
"strings"
"testing"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginchecker"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/grafana/grafana/pkg/services/pluginsintegration/provisionedplugins"
)
type mockPluginPreinstall struct {
pluginchecker.Preinstall
}
func (m *mockPluginPreinstall) IsPinned(pluginID string) bool {
return false
}
func TestPluginUpdateChecker_HasUpdate(t *testing.T) {
t.Run("update is available", func(t *testing.T) {
updateCheckURL, _ := url.Parse("https://grafana.com/api/plugins/versioncheck")
svc := PluginsService{
availableUpdates: map[string]availableUpdate{
"test-ds": {
localVersion: "0.9.0",
availableVersion: "1.0.0",
},
},
pluginStore: &pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{
{
JSONData: plugins.JSONData{
ID: "test-ds",
Info: plugins.Info{Version: "0.9.0"},
},
},
},
},
updateCheckURL: updateCheckURL,
updateChecker: pluginchecker.ProvideService(managedplugins.NewNoop(), provisionedplugins.NewNoop(), &mockPluginPreinstall{}),
features: &featuremgmt.FeatureManager{},
}
update, exists := svc.HasUpdate(context.Background(), "test-ds")
require.True(t, exists)
require.Equal(t, "1.0.0", update)
})
t.Run("update is not available", func(t *testing.T) {
updateCheckURL, _ := url.Parse("https://grafana.com/api/plugins/versioncheck")
svc := PluginsService{
availableUpdates: map[string]availableUpdate{
"test-panel": {
localVersion: "0.9.0",
availableVersion: "0.9.0",
},
"test-app": {
localVersion: "0.9.0",
availableVersion: "0.9.0",
},
},
pluginStore: &pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{
{
JSONData: plugins.JSONData{
ID: "test-ds",
Info: plugins.Info{Version: "0.9.0"},
},
},
{
JSONData: plugins.JSONData{
ID: "test-panel",
Info: plugins.Info{Version: "0.9.0"},
},
},
{
JSONData: plugins.JSONData{
ID: "test-app",
Info: plugins.Info{Version: "0.9.0"},
},
},
},
},
updateCheckURL: updateCheckURL,
updateChecker: pluginchecker.ProvideService(managedplugins.NewNoop(), provisionedplugins.NewNoop(), &mockPluginPreinstall{}),
}
update, exists := svc.HasUpdate(context.Background(), "test-ds")
require.False(t, exists)
require.Empty(t, update)
update, exists = svc.HasUpdate(context.Background(), "test-panel")
require.False(t, exists)
require.Empty(t, update)
update, exists = svc.HasUpdate(context.Background(), "test-app")
require.False(t, exists)
require.Empty(t, update)
})
t.Run("update is available but plugin is not in store", func(t *testing.T) {
updateCheckURL, _ := url.Parse("https://grafana.com/api/plugins/versioncheck")
svc := PluginsService{
availableUpdates: map[string]availableUpdate{
"test-panel": {
localVersion: "0.9.0",
availableVersion: "0.9.0",
},
},
pluginStore: &pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{
{
JSONData: plugins.JSONData{
ID: "test-ds",
Info: plugins.Info{Version: "1.0.0"},
},
},
},
},
updateCheckURL: updateCheckURL,
}
update, exists := svc.HasUpdate(context.Background(), "test-panel")
require.False(t, exists)
require.Empty(t, update)
update, exists = svc.HasUpdate(context.Background(), "test-ds")
require.False(t, exists)
require.Empty(t, update)
})
}
func TestPluginUpdateChecker_checkForUpdates(t *testing.T) {
t.Run("update is available", func(t *testing.T) {
jsonResp := `[
{
"slug": "test-ds",
"version": "1.0.12"
},
{
"slug": "test-panel",
"version": "2.5.7"
},
{
"slug": "test-core-panel",
"version": "1.0.0"
}
]`
updateCheckURL, _ := url.Parse("https://grafana.com/api/plugins/versioncheck")
svc := PluginsService{
availableUpdates: map[string]availableUpdate{
"test-app": {
localVersion: "0.5.0",
availableVersion: "1.0.0",
},
},
pluginStore: &pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{
{
JSONData: plugins.JSONData{
ID: "test-ds",
Info: plugins.Info{Version: "0.9.0"},
Type: plugins.TypeDataSource,
},
Class: plugins.ClassExternal,
},
{
JSONData: plugins.JSONData{
ID: "test-app",
Info: plugins.Info{Version: "0.5.0"},
Type: plugins.TypeApp,
},
Class: plugins.ClassExternal,
},
{
JSONData: plugins.JSONData{
ID: "test-panel",
Info: plugins.Info{Version: "2.5.7"},
Type: plugins.TypePanel,
},
Class: plugins.ClassExternal,
},
{
JSONData: plugins.JSONData{
ID: "test-core-panel",
Info: plugins.Info{Version: "0.0.1"},
Type: plugins.TypePanel,
},
Class: plugins.ClassCore,
},
},
},
httpClient: &fakeHTTPClient{
fakeResp: jsonResp,
},
log: log.NewNopLogger(),
tracer: tracing.InitializeTracerForTest(),
updateCheckURL: updateCheckURL,
updateChecker: pluginchecker.ProvideService(managedplugins.NewNoop(), provisionedplugins.NewNoop(), &mockPluginPreinstall{}),
features: &featuremgmt.FeatureManager{},
}
svc.instrumentedCheckForUpdates(context.Background())
require.Equal(t, 1, len(svc.availableUpdates))
require.Equal(t, "1.0.12", svc.availableUpdates["test-ds"].availableVersion)
update, exists := svc.HasUpdate(context.Background(), "test-ds")
require.True(t, exists)
require.Equal(t, "1.0.12", update)
require.Empty(t, svc.availableUpdates["test-app"])
update, exists = svc.HasUpdate(context.Background(), "test-app")
require.False(t, exists)
require.Empty(t, update)
require.Empty(t, svc.availableUpdates["test-panel"])
update, exists = svc.HasUpdate(context.Background(), "test-panel")
require.False(t, exists)
require.Empty(t, update)
require.Empty(t, svc.availableUpdates["test-core-panel"])
})
}
func TestPluginUpdateChecker_updateAll(t *testing.T) {
t.Run("update is available", func(t *testing.T) {
pluginsFakeStore := map[string]string{}
availableUpdates := map[string]availableUpdate{
"test-app-0": {
localVersion: "0.9.0",
availableVersion: "1.0.0",
},
"test-app-1": {
localVersion: "0.9.0",
availableVersion: "1.0.0",
},
"test-app-2": {
localVersion: "0.9.0",
availableVersion: "1.0.0",
},
}
svc := PluginsService{
availableUpdates: availableUpdates,
log: log.NewNopLogger(),
tracer: tracing.InitializeTracerForTest(),
pluginInstaller: &fakes.FakePluginInstaller{
AddFunc: func(ctx context.Context, pluginID, version string, opts plugins.AddOpts) error {
pluginsFakeStore[pluginID] = version
return nil
},
RemoveFunc: func(ctx context.Context, pluginID, version string) error {
delete(pluginsFakeStore, pluginID)
return nil
},
},
}
svc.updateAll(context.Background())
require.Equal(t, 0, len(svc.availableUpdates))
require.Equal(t, len(availableUpdates), len(pluginsFakeStore))
for pluginID, availableUpdate := range availableUpdates {
require.Equal(t, availableUpdate.availableVersion, pluginsFakeStore[pluginID])
}
})
}
type fakeHTTPClient struct {
fakeResp string
requestURL string
}
func (c *fakeHTTPClient) Do(req *http.Request) (*http.Response, error) {
c.requestURL = req.URL.String()
resp := &http.Response{
Body: io.NopCloser(strings.NewReader(c.fakeResp)),
}
return resp, nil
}