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:
+19
-19
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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 (
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user