Plugins: Allow disabling angular deprecation UI for specific plugins (#77026)

* Plugins:Allow disabling angular deprecation UI for specific plugins

* add backend test

* changed test names

* lint

* Removed angular properties from DataSourceDTO

* Update tests

* Move angularDetected and hideAngularDeprecation in angularMeta property

* Fix angular property name in AppPluginConfig

* Fix reference to angularMeta.detected

* Fix hide_angular_deprecation not working for core plugins

* lint
This commit is contained in:
Giuseppe Guerra
2023-11-10 11:44:54 +01:00
committed by GitHub
parent 934456dc1c
commit da117aea1c
21 changed files with 164 additions and 92 deletions
+19 -19
View File
@@ -71,18 +71,18 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
}
panels[panel.ID] = plugins.PanelDTO{
ID: panel.ID,
Name: panel.Name,
AliasIDs: panel.AliasIDs,
Info: panel.Info,
Module: panel.Module,
BaseURL: panel.BaseURL,
SkipDataQuery: panel.SkipDataQuery,
HideFromList: panel.HideFromList,
ReleaseState: string(panel.State),
Signature: string(panel.Signature),
Sort: getPanelSort(panel.ID),
AngularDetected: panel.AngularDetected,
ID: panel.ID,
Name: panel.Name,
AliasIDs: panel.AliasIDs,
Info: panel.Info,
Module: panel.Module,
BaseURL: panel.BaseURL,
SkipDataQuery: panel.SkipDataQuery,
HideFromList: panel.HideFromList,
ReleaseState: string(panel.State),
Signature: string(panel.Signature),
Sort: getPanelSort(panel.ID),
Angular: panel.Angular,
}
}
@@ -336,8 +336,8 @@ func (hs *HTTPServer) getFSDataSources(c *contextmodel.ReqContext, availablePlug
Signature: plugin.Signature,
Module: plugin.Module,
BaseURL: plugin.BaseURL,
Angular: plugin.Angular,
}
dsDTO.AngularDetected = plugin.AngularDetected
if ds.JsonData == nil {
dsDTO.JSONData = make(map[string]any)
@@ -419,8 +419,8 @@ func (hs *HTTPServer) getFSDataSources(c *contextmodel.ReqContext, availablePlug
Signature: ds.Signature,
Module: ds.Module,
BaseURL: ds.BaseURL,
Angular: ds.Angular,
},
AngularDetected: ds.AngularDetected,
}
if ds.Name == grafanads.DatasourceName {
dto.ID = grafanads.DatasourceID
@@ -435,11 +435,11 @@ func (hs *HTTPServer) getFSDataSources(c *contextmodel.ReqContext, availablePlug
func newAppDTO(plugin pluginstore.Plugin, settings pluginsettings.InfoDTO) *plugins.AppDTO {
app := &plugins.AppDTO{
ID: plugin.ID,
Version: plugin.Info.Version,
Path: plugin.Module,
Preload: false,
AngularDetected: plugin.AngularDetected,
ID: plugin.ID,
Version: plugin.Info.Version,
Path: plugin.Module,
Preload: false,
Angular: plugin.Angular,
}
if settings.Enabled {
+6 -6
View File
@@ -295,7 +295,7 @@ func TestHTTPServer_GetFrontendSettings_apps(t *testing.T) {
Type: plugins.TypeApp,
Preload: true,
},
AngularDetected: true,
Angular: plugins.AngularMeta{Detected: true},
},
},
}
@@ -308,11 +308,11 @@ func TestHTTPServer_GetFrontendSettings_apps(t *testing.T) {
expected: settings{
Apps: map[string]*plugins.AppDTO{
"test-app": {
ID: "test-app",
Preload: true,
Path: "/test-app/module.js",
Version: "0.5.0",
AngularDetected: true,
ID: "test-app",
Preload: true,
Path: "/test-app/module.js",
Version: "0.5.0",
Angular: plugins.AngularMeta{Detected: true},
},
},
},
+2 -2
View File
@@ -139,7 +139,7 @@ func (hs *HTTPServer) GetPluginList(c *contextmodel.ReqContext) response.Respons
SignatureType: pluginDef.SignatureType,
SignatureOrg: pluginDef.SignatureOrg,
AccessControl: pluginsMetadata[pluginDef.ID],
AngularDetected: pluginDef.AngularDetected,
AngularDetected: pluginDef.Angular.Detected,
}
update, exists := hs.pluginsUpdateChecker.HasUpdate(c.Req.Context(), pluginDef.ID)
@@ -196,7 +196,7 @@ func (hs *HTTPServer) GetPluginSettingByID(c *contextmodel.ReqContext) response.
SignatureType: plugin.SignatureType,
SignatureOrg: plugin.SignatureOrg,
SecureJsonFields: map[string]bool{},
AngularDetected: plugin.AngularDetected,
AngularDetected: plugin.Angular.Detected,
}
if plugin.IsApp() {
@@ -95,7 +95,7 @@ func (a *AngularDetector) Validate(ctx context.Context, p *plugins.Plugin) error
var err error
cctx, canc := context.WithTimeout(ctx, time.Second*10)
p.AngularDetected, err = a.angularInspector.Inspect(cctx, p)
p.Angular.Detected, err = a.angularInspector.Inspect(cctx, p)
canc()
if err != nil {
@@ -103,11 +103,11 @@ func (a *AngularDetector) Validate(ctx context.Context, p *plugins.Plugin) error
}
// Do not initialize plugins if they're using Angular and Angular support is disabled
if p.AngularDetected && !a.cfg.AngularSupportEnabled {
if p.Angular.Detected && !a.cfg.AngularSupportEnabled {
a.log.Error("Refusing to initialize plugin because it's using Angular, which has been disabled", "pluginId", p.ID)
return errors.New("angular plugins are not supported")
}
}
p.Angular.HideDeprecation = a.cfg.PluginSettings[p.ID]["hide_angular_deprecation"] == "true"
return nil
}
+33 -30
View File
@@ -208,22 +208,23 @@ type PluginMetaDTO struct {
Module string `json:"module"`
BaseURL string `json:"baseUrl"`
Angular AngularMeta `json:"angular"`
}
type DataSourceDTO struct {
ID int64 `json:"id,omitempty"`
UID string `json:"uid,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
PluginMeta *PluginMetaDTO `json:"meta"`
URL string `json:"url,omitempty"`
IsDefault bool `json:"isDefault"`
Access string `json:"access,omitempty"`
Preload bool `json:"preload"`
Module string `json:"module,omitempty"`
JSONData map[string]any `json:"jsonData"`
ReadOnly bool `json:"readOnly"`
AngularDetected bool `json:"angularDetected"`
ID int64 `json:"id,omitempty"`
UID string `json:"uid,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
PluginMeta *PluginMetaDTO `json:"meta"`
URL string `json:"url,omitempty"`
IsDefault bool `json:"isDefault"`
Access string `json:"access,omitempty"`
Preload bool `json:"preload"`
Module string `json:"module,omitempty"`
JSONData map[string]any `json:"jsonData"`
ReadOnly bool `json:"readOnly"`
BasicAuth string `json:"basicAuth,omitempty"`
WithCredentials bool `json:"withCredentials,omitempty"`
@@ -243,26 +244,28 @@ type DataSourceDTO struct {
}
type PanelDTO struct {
ID string `json:"id"`
Name string `json:"name"`
AliasIDs []string `json:"aliasIds,omitempty"`
Info Info `json:"info"`
HideFromList bool `json:"hideFromList"`
Sort int `json:"sort"`
SkipDataQuery bool `json:"skipDataQuery"`
ReleaseState string `json:"state"`
BaseURL string `json:"baseUrl"`
Signature string `json:"signature"`
Module string `json:"module"`
AngularDetected bool `json:"angularDetected"`
ID string `json:"id"`
Name string `json:"name"`
AliasIDs []string `json:"aliasIds,omitempty"`
Info Info `json:"info"`
HideFromList bool `json:"hideFromList"`
Sort int `json:"sort"`
SkipDataQuery bool `json:"skipDataQuery"`
ReleaseState string `json:"state"`
BaseURL string `json:"baseUrl"`
Signature string `json:"signature"`
Module string `json:"module"`
Angular AngularMeta `json:"angular"`
}
type AppDTO struct {
ID string `json:"id"`
Path string `json:"path"`
Version string `json:"version"`
Preload bool `json:"preload"`
AngularDetected bool `json:"angularDetected"`
ID string `json:"id"`
Path string `json:"path"`
Version string `json:"version"`
Preload bool `json:"preload"`
Angular AngularMeta `json:"angular"`
}
const (
+6 -1
View File
@@ -55,7 +55,7 @@ type Plugin struct {
Module string
BaseURL string
AngularDetected bool
Angular AngularMeta
ExternalService *auth.ExternalService
@@ -67,6 +67,11 @@ type Plugin struct {
mu sync.Mutex
}
type AngularMeta struct {
Detected bool `json:"detected"`
HideDeprecation bool `json:"hideDeprecation"`
}
// JSONData represents the plugin's plugin.json
type JSONData struct {
// Common settings
@@ -1221,9 +1221,9 @@ func TestLoader_AngularClass(t *testing.T) {
require.NoError(t, err)
require.Len(t, p, 1, "should load 1 plugin")
if tc.expAngularDetectionRun {
require.True(t, p[0].AngularDetected, "angular detection should run")
require.True(t, p[0].Angular.Detected, "angular detection should run")
} else {
require.False(t, p[0].AngularDetected, "angular detection should not run")
require.False(t, p[0].Angular.Detected, "angular detection should not run")
}
})
}
@@ -1279,6 +1279,49 @@ func TestLoader_Load_Angular(t *testing.T) {
}
}
func TestLoader_HideAngularDeprecation(t *testing.T) {
fakePluginSource := &fakes.FakePluginSource{
PluginClassFunc: func(ctx context.Context) plugins.Class {
return plugins.ClassExternal
},
PluginURIsFunc: func(ctx context.Context) []string {
return []string{filepath.Join(testDataDir(t), "valid-v2-signature")}
},
}
for _, tc := range []struct {
name string
cfg *config.Cfg
expHideAngularDeprecation bool
}{
{name: `without "hide_angular_deprecation" setting`, cfg: &config.Cfg{
AngularSupportEnabled: true,
PluginSettings: setting.PluginSettings{},
}},
{name: `with "hide_angular_deprecation" = true`, cfg: &config.Cfg{
AngularSupportEnabled: true,
PluginSettings: setting.PluginSettings{
"plugin-id": map[string]string{"hide_angular_deprecation": "true"},
}},
},
{name: `with "hide_angular_deprecation" = false`, cfg: &config.Cfg{
AngularSupportEnabled: true,
PluginSettings: setting.PluginSettings{
"plugin-id": map[string]string{"hide_angular_deprecation": "false"},
}},
},
} {
t.Run(tc.name, func(t *testing.T) {
l := newLoaderWithOpts(t, tc.cfg, loaderDepOpts{
angularInspector: angularinspector.AlwaysAngularFakeInspector,
})
p, err := l.Load(context.Background(), fakePluginSource)
require.NoError(t, err)
require.Len(t, p, 1, "should load 1 plugin")
require.Equal(t, tc.expHideAngularDeprecation, p[0].Angular.HideDeprecation)
})
}
}
func TestLoader_Load_NestedPlugins(t *testing.T) {
parent := &plugins.Plugin{
JSONData: plugins.JSONData{
@@ -30,7 +30,7 @@ type Plugin struct {
Module string
BaseURL string
AngularDetected bool
Angular plugins.AngularMeta
ExternalService *auth.ExternalService
}
@@ -72,7 +72,8 @@ func ToGrafanaDTO(p *plugins.Plugin) Plugin {
SignatureError: p.SignatureError,
Module: p.Module,
BaseURL: p.BaseURL,
AngularDetected: p.AngularDetected,
ExternalService: p.ExternalService,
Angular: p.Angular,
}
}